commit 8a4210f3803eed236a51af9081da330a62eaf2fb Author: ylhan Date: Thu Aug 20 17:42:14 2026 +0800 将 note 笔记库同步到 note_sync,AI_compiler 作为 submodule diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c8ce1f8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "AI_compiler"] + path = AI_compiler + url = https://git.hyonglin.top/ylhan/note_AI_compiler.git diff --git a/.obsidian/app.json b/.obsidian/app.json new file mode 100644 index 0000000..f699f2f --- /dev/null +++ b/.obsidian/app.json @@ -0,0 +1,9 @@ +{ + "pdfExportSettings": { + "includeName": true, + "pageSize": "Letter", + "landscape": false, + "margin": "0", + "downscalePercent": 100 + } +} \ No newline at end of file diff --git a/.obsidian/appearance.json b/.obsidian/appearance.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.obsidian/appearance.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/.obsidian/core-plugins.json b/.obsidian/core-plugins.json new file mode 100644 index 0000000..639b90d --- /dev/null +++ b/.obsidian/core-plugins.json @@ -0,0 +1,33 @@ +{ + "file-explorer": true, + "global-search": true, + "switcher": true, + "graph": true, + "backlink": true, + "canvas": true, + "outgoing-link": true, + "tag-pane": true, + "footnotes": false, + "properties": true, + "page-preview": true, + "daily-notes": true, + "templates": true, + "note-composer": true, + "command-palette": true, + "slash-command": false, + "editor-status": true, + "bookmarks": true, + "markdown-importer": false, + "zk-prefixer": false, + "random-note": false, + "outline": true, + "word-count": true, + "slides": false, + "audio-recorder": false, + "workspaces": false, + "file-recovery": true, + "publish": false, + "sync": true, + "bases": true, + "webviewer": false +} \ No newline at end of file diff --git a/.obsidian/graph.json b/.obsidian/graph.json new file mode 100644 index 0000000..cf4b782 --- /dev/null +++ b/.obsidian/graph.json @@ -0,0 +1,22 @@ +{ + "collapse-filter": false, + "search": "", + "showTags": false, + "showAttachments": false, + "hideUnresolved": false, + "showOrphans": false, + "collapse-color-groups": false, + "colorGroups": [], + "collapse-display": true, + "showArrow": false, + "textFadeMultiplier": 0, + "nodeSizeMultiplier": 1, + "lineSizeMultiplier": 1, + "collapse-forces": true, + "centerStrength": 0.518713248970312, + "repelStrength": 10, + "linkStrength": 1, + "linkDistance": 250, + "scale": 1, + "close": false +} \ No newline at end of file diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json new file mode 100644 index 0000000..d71637f --- /dev/null +++ b/.obsidian/workspace.json @@ -0,0 +1,254 @@ +{ + "main": { + "id": "baaef7f0d0c37abd", + "type": "split", + "children": [ + { + "id": "eaf4cbbe01345c1b", + "type": "tabs", + "children": [ + { + "id": "a64a4cd245fb22ec", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "履带车T10遥控器协议与操作说明.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "履带车T10遥控器协议与操作说明" + } + }, + { + "id": "ead3240747740b7d", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "ros/ros2/ros2_control/环境.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "环境" + } + }, + { + "id": "115caef4c284a702", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "自建服务/Silverbullet部署指南.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "Silverbullet部署指南" + } + } + ], + "currentTab": 2 + } + ], + "direction": "vertical" + }, + "left": { + "id": "b2e8a489e5c74a84", + "type": "split", + "children": [ + { + "id": "20cece044921a370", + "type": "tabs", + "children": [ + { + "id": "0a844a1838a0afc7", + "type": "leaf", + "state": { + "type": "file-explorer", + "state": { + "sortOrder": "alphabetical", + "autoReveal": false, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-folder-closed", + "title": "文件列表" + } + }, + { + "id": "7d36ad1a0e870585", + "type": "leaf", + "state": { + "type": "search", + "state": { + "query": "", + "matchingCase": false, + "explainSearch": false, + "collapseAll": false, + "extraContext": false, + "sortOrder": "alphabetical" + }, + "icon": "lucide-search", + "title": "搜索" + } + }, + { + "id": "bda7c9d5257639de", + "type": "leaf", + "state": { + "type": "bookmarks", + "state": {}, + "icon": "lucide-bookmark", + "title": "书签" + } + } + ] + } + ], + "direction": "horizontal", + "width": 300 + }, + "right": { + "id": "151f2874cea23ad8", + "type": "split", + "children": [ + { + "id": "7c0d580356baa113", + "type": "tabs", + "children": [ + { + "id": "7cc083e6d69c3d69", + "type": "leaf", + "state": { + "type": "backlink", + "state": { + "file": "大模型/DeepSeek V4 系列.md", + "collapseAll": false, + "extraContext": false, + "sortOrder": "alphabetical", + "showSearch": false, + "searchQuery": "", + "backlinkCollapsed": false, + "unlinkedCollapsed": true + }, + "icon": "links-coming-in", + "title": "DeepSeek V4 系列 的反向链接列表" + } + }, + { + "id": "adaff8d134c6c028", + "type": "leaf", + "state": { + "type": "outgoing-link", + "state": { + "file": "履带车T10遥控器协议与操作说明.md", + "linksCollapsed": false, + "unlinkedCollapsed": true + }, + "icon": "links-going-out", + "title": "履带车T10遥控器协议与操作说明 的出链列表" + } + }, + { + "id": "2d6594801d830dfe", + "type": "leaf", + "state": { + "type": "tag", + "state": { + "sortOrder": "frequency", + "useHierarchy": true, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-tags", + "title": "标签" + } + }, + { + "id": "bb36402a7e978df7", + "type": "leaf", + "state": { + "type": "all-properties", + "state": { + "sortOrder": "frequency", + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-archive", + "title": "添加笔记属性" + } + }, + { + "id": "d3338eaffa18cf65", + "type": "leaf", + "state": { + "type": "outline", + "state": { + "file": "履带车T10遥控器协议与操作说明.md", + "followCursor": false, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-list", + "title": "履带车T10遥控器协议与操作说明 的大纲" + } + } + ] + } + ], + "direction": "horizontal", + "width": 300, + "collapsed": true + }, + "left-ribbon": { + "hiddenItems": { + "switcher:打开快速切换": false, + "graph:查看关系图谱": false, + "canvas:新建白板": false, + "daily-notes:打开/创建今天的日记": false, + "templates:插入模板": false, + "command-palette:打开命令面板": false, + "bases:新建数据库": false + } + }, + "active": "115caef4c284a702", + "lastOpenFiles": [ + "大模型/FFN 前馈网络详解.md", + "自建服务/Silverbullet部署指南.md", + "自建服务", + "技术趋势/AI编译器现状与前景.md", + "大模型/DeepSeek V4 系列.md", + "技术趋势", + "ros/ros2/ros2_control/环境.md", + "未命名 1.base", + "未命名.base", + "大模型/MoE 混合专家架构.md", + "大模型/Transformer 架构详解.md", + "大模型/MoE 混合专家架构.md.tmp.33168.91e110d04189", + "大模型/MoE 混合专家架构.md.tmp.33168.aec6279f2917", + "大模型/大模型架构基础.md", + "工作/机械臂分析.md", + "工作/履带车T10遥控器协议与操作说明.md", + "工作", + "大模型/多模态大模型.md", + "大模型架构基础.md", + "autoware_w7/w7.md", + "大模型", + "工作/nav2 优缺点.md", + "工作/VCU控制逻辑(v0.2).md", + "工作/VCU控制逻辑_精简版.md", + "ros/ros2/nav2/debug.md", + "VCU控制逻辑(v0.2).md.tmp.17548.1776933572846", + "ros/ros2/nav2/debug", + "工作/Pasted image 20260402112951.png", + "ros/ros2/nav2/nav2_bringup_gps_demo.md", + "工作/Pasted image 20260402112914.png", + "ros/ros2/nav2/nav2.md", + "ros/履带底盘机械臂.md", + "ros/ros2/安装配置/ros2_structure.md", + "ros/ros2/概念/基础概念.md" + ] +} \ No newline at end of file diff --git a/AI_compiler b/AI_compiler new file mode 160000 index 0000000..86ed9b3 --- /dev/null +++ b/AI_compiler @@ -0,0 +1 @@ +Subproject commit 86ed9b3b1a5f80f37261f4138c35fc8bbb94949d diff --git a/autoware_w7/w7.md b/autoware_w7/w7.md new file mode 100644 index 0000000..f8c7cc9 --- /dev/null +++ b/autoware_w7/w7.md @@ -0,0 +1,233 @@ +# Autoware W7 启动概览 + + + +以下内容基于命令: + + + +ros2 launch autoware_launch autoware.launch.xml \ + +  sensor_model:=sample_sensor_kit \ + +  vehicle_model:=sample_vehicle \ + +  vehicle_id:=W7 \ + +  map_path:=/media/nvidia/nvme0n1pnvme0n1p1/autoware_map/test_map_A4_and_PARK/ + + + +## 模块关系(Mermaid) + + + +```mermaid + +graph LR + +  subgraph SENSING["感知层 Sensing"] + +    SENSINGN(Pointcloud / Camera / Radar) + +    PCCTR[pointcloud_container] + +  end + + + +  subgraph MAPGRP["地图 Map"] + +    PC_MAP(Pointcloud Map) + +    LL_MAP(Lanelet2 Map) + +  end + + + +  subgraph LOCAL["定位 Localization"] + +    LOCN(Localization) + +  end + + + +  subgraph PER["感知 Perception"] + +    PERN(Detection / Tracking / TLR) + +  end + + + +  subgraph PLAN["规划 Planning"] + +    PLANN(Mission / Behavior / Motion) + +  end + + + +  subgraph CTRL["控制 Control"] + +    CTRLN(Trajectory Follower) + +  end + + + +  subgraph VEH["车辆 Vehicle"] + +    VIF(Vehicle Interface) + +    RSP(robot_state_publisher) + +  end + + + +  RVIZ[RViz2] + + + +  SENSINGN -->|点云/图像| PERN + +  SENSINGN -->|点云| LOCN + +  PCCTR -->|聚合点云| PERN + +  PCCTR -->|聚合点云| LOCN + +  PC_MAP -->|点云地图| LOCN + +  LL_MAP -->|lanelet2| PLANN + +  LOCN -->|pose/tf| PLANN + +  PERN -->|detected_objects| PLANN + +  PLANN -->|trajectory| CTRLN + +  CTRLN -->|vehicle_cmd| VIF + +  VIF -->|状态| PLANN + +  RSP -->|tf| RVIZ + +``` + + + +## 主要模块与说明 + + + +- Vehicle:车辆描述与接口(`robot_state_publisher`、`vehicle_interface`、`raw_vehicle_cmd_converter`) + +- System:系统监控、诊断(health、diagnostics) + +- Map:点云地图 (`pointcloud_map.pcd`) 与 Lanelet2 (`lanelet2_map.osm`) 加载 + +- Sensing:传感器驱动、预处理、`pointcloud_container` + +- Localization:ND T / yabloc / eagleye / EKF 等定位组件,依赖点云与地图 + +- Perception:地面分割、检测、跟踪、交通灯识别、融合 + +- Planning:mission、behavior、motion(包含 diffusion_planner 可选) + +- Control:轨迹跟踪(MPC/PID 等)并输出 `vehicle_cmd` + +- API/Tools:Autoware API、RViz2 等 + + + +## 收集到的关键节点(从相关 launch 文件) + + + +- `robot_state_publisher` (Vehicle) + +- `raw_vehicle_cmd_converter` (Vehicle Interface) + +- `map_hash_generator` (Map) + +- `trajectory_relay`(topic_tools relay,将 `/planning/trajectory` 转发到 `/planning/scenario_planning/trajectory`) + + + +- Sensing / Sensor kit 示例节点: + +  - `tl_camera_info_relay`(topic_tools relay for camera) + +  - `tl_compressed_image_relay`(topic_tools relay) + +  - `imu_to_autoware_orientation`(GNSS/IMU 预处理) + +  - `imu_data_compat_relay`(topic_tools relay) + +  - `tag_serial_driver`(IMU 驱动) + + + +- Localization / eagleye 相关节点(部分): + +  - `gnss_converter_node`(eagleye_gnss_converter) + +  - `eagleye_output_twist_relay`(topic_tools relay) + +  - `twist_relay`, `tf_converted_imu`, `velocity_scale_factor_node`, `yaw_rate_offset_*`, `heading_*`, `position`, `smoothing`, `height`, `monitor`(eagleye_rt 包内多个辅助节点) + + + +- Perception 相关节点(示例): + +  - `simple_object_merger`(autoware_simple_object_merger) + +  - `empty_objects_publisher`(autoware_dummy_perception_publisher,用于仿真/占位) + + + +- Planning / Diffusion 示例节点: + +  - `velocity_smoother`(demo_nodes_cpp parameter_blackboard 用作示例) + + + +- Control 相关节点: + +  - `controller_node_exe`(autoware_smart_mpc_trajectory_follower 的 Python 接口) + + + +- Simulator / 工具节点(示例): + +  - `elevation_map_loader`, `autoware_vehicle_velocity_converter`, `autoware_scenario_simulator_v2_adapter_node` + + + +> 注:上面列举的是主要/代表性节点,Autoware 启动会包含大量子包内的节点(许多由组件的 `launch.xml` 或 `launch.py` 再次 include)。如需我逐个组件展开完整节点列表,我可以继续递归读取每个组件的 launch 目录并生成更详尽的清单。 + + + +--- + + + +文件已保存到: + +- 工作区(副本,可点击查看): `docs/autoware_w7/Autoware_W7_overview.md` + +- 你的指定路径副本: `/media/nvidia/nvme0n1pnvme0n1p1/ylhan/autoware_w7/Autoware_W7_overview.md` + + + +如果需要,我可以: + +- 生成更详细的每个子包启动节点清单并保存为文本或 CSV; + +- 将 Mermaid 图另存为 SVG; + +- 针对 `vehicle_interface.launch.xml`、`sensing.launch.xml` 等列出完整的 node 列表。 \ No newline at end of file diff --git a/ros/.obsidian/app.json b/ros/.obsidian/app.json new file mode 100644 index 0000000..e609a07 --- /dev/null +++ b/ros/.obsidian/app.json @@ -0,0 +1,3 @@ +{ + "promptDelete": false +} \ No newline at end of file diff --git a/ros/.obsidian/appearance.json b/ros/.obsidian/appearance.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/ros/.obsidian/appearance.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/ros/.obsidian/core-plugins.json b/ros/.obsidian/core-plugins.json new file mode 100644 index 0000000..639b90d --- /dev/null +++ b/ros/.obsidian/core-plugins.json @@ -0,0 +1,33 @@ +{ + "file-explorer": true, + "global-search": true, + "switcher": true, + "graph": true, + "backlink": true, + "canvas": true, + "outgoing-link": true, + "tag-pane": true, + "footnotes": false, + "properties": true, + "page-preview": true, + "daily-notes": true, + "templates": true, + "note-composer": true, + "command-palette": true, + "slash-command": false, + "editor-status": true, + "bookmarks": true, + "markdown-importer": false, + "zk-prefixer": false, + "random-note": false, + "outline": true, + "word-count": true, + "slides": false, + "audio-recorder": false, + "workspaces": false, + "file-recovery": true, + "publish": false, + "sync": true, + "bases": true, + "webviewer": false +} \ No newline at end of file diff --git a/ros/.obsidian/graph.json b/ros/.obsidian/graph.json new file mode 100644 index 0000000..5185ea5 --- /dev/null +++ b/ros/.obsidian/graph.json @@ -0,0 +1,30 @@ +{ + "collapse-filter": false, + "search": "", + "showTags": false, + "showAttachments": false, + "hideUnresolved": false, + "showOrphans": true, + "collapse-color-groups": false, + "colorGroups": [ + { + "query": "tag:", + "color": { + "a": 1, + "rgb": 14048348 + } + } + ], + "collapse-display": true, + "showArrow": false, + "textFadeMultiplier": 0, + "nodeSizeMultiplier": 1, + "lineSizeMultiplier": 1, + "collapse-forces": true, + "centerStrength": 0.518713248970312, + "repelStrength": 10, + "linkStrength": 1, + "linkDistance": 250, + "scale": 1, + "close": true +} \ No newline at end of file diff --git a/ros/.obsidian/workspace.json b/ros/.obsidian/workspace.json new file mode 100644 index 0000000..3ba29fb --- /dev/null +++ b/ros/.obsidian/workspace.json @@ -0,0 +1,201 @@ +{ + "main": { + "id": "914c9e8d9774b62f", + "type": "split", + "children": [ + { + "id": "22be749e4ad854f0", + "type": "tabs", + "children": [ + { + "id": "0f14a7f3e342ee77", + "type": "leaf", + "state": { + "type": "markdown", + "state": { + "file": "ros2/概念/基础概念.md", + "mode": "preview", + "source": false + }, + "icon": "lucide-file", + "title": "基础概念" + } + } + ] + } + ], + "direction": "vertical" + }, + "left": { + "id": "3d550c51e4dc52dd", + "type": "split", + "children": [ + { + "id": "64ee6b66868da0e5", + "type": "tabs", + "children": [ + { + "id": "4a3332297ce1ac65", + "type": "leaf", + "state": { + "type": "file-explorer", + "state": { + "sortOrder": "alphabetical", + "autoReveal": false + }, + "icon": "lucide-folder-closed", + "title": "文件列表" + } + }, + { + "id": "94dc470ccbf6e453", + "type": "leaf", + "state": { + "type": "search", + "state": { + "query": "", + "matchingCase": false, + "explainSearch": false, + "collapseAll": false, + "extraContext": false, + "sortOrder": "alphabetical" + }, + "icon": "lucide-search", + "title": "搜索" + } + }, + { + "id": "a49ddb63b7b71d3d", + "type": "leaf", + "state": { + "type": "bookmarks", + "state": {}, + "icon": "lucide-bookmark", + "title": "书签" + } + } + ] + } + ], + "direction": "horizontal", + "width": 300 + }, + "right": { + "id": "94ee3ffae97277f1", + "type": "split", + "children": [ + { + "id": "30c22dd0ea555284", + "type": "tabs", + "children": [ + { + "id": "e08ac0b7a754e82a", + "type": "leaf", + "state": { + "type": "backlink", + "state": { + "collapseAll": false, + "extraContext": false, + "sortOrder": "alphabetical", + "showSearch": false, + "searchQuery": "", + "backlinkCollapsed": false, + "unlinkedCollapsed": true + }, + "icon": "links-coming-in", + "title": "反向链接" + } + }, + { + "id": "c28b4721bbc7549d", + "type": "leaf", + "state": { + "type": "outgoing-link", + "state": { + "linksCollapsed": false, + "unlinkedCollapsed": true + }, + "icon": "links-going-out", + "title": "出链" + } + }, + { + "id": "951c9abc2fe22169", + "type": "leaf", + "state": { + "type": "tag", + "state": { + "sortOrder": "frequency", + "useHierarchy": true, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-tags", + "title": "标签" + } + }, + { + "id": "ced613ec67772cc8", + "type": "leaf", + "state": { + "type": "all-properties", + "state": { + "sortOrder": "frequency", + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-archive", + "title": "添加笔记属性" + } + }, + { + "id": "31cad42ee1968b90", + "type": "leaf", + "state": { + "type": "outline", + "state": { + "followCursor": false, + "showSearch": false, + "searchQuery": "" + }, + "icon": "lucide-list", + "title": "大纲" + } + } + ] + } + ], + "direction": "horizontal", + "width": 300, + "collapsed": true + }, + "left-ribbon": { + "hiddenItems": { + "switcher:打开快速切换": false, + "graph:查看关系图谱": false, + "canvas:新建白板": false, + "daily-notes:打开/创建今天的日记": false, + "templates:插入模板": false, + "command-palette:打开命令面板": false, + "bases:新建数据库": false + } + }, + "active": "0f14a7f3e342ee77", + "lastOpenFiles": [ + "ros2/概念/基础概念.md", + "ros2/安装配置/环境配置.md", + "ros2/概念", + "ros2/新建文件夹", + "未命名", + "ros2/安装配置", + "ros2/安装配置/代码更新_zh.md", + "未命名.md", + "ros2/安装配置/ros2_structure.md", + "ros2/安装配置/安装_zh.md", + "ros2/安装配置/安装.md", + "欢迎.md", + "创建链接.md", + "ros2", + "desktop.ini" + ] +} \ No newline at end of file diff --git a/ros/ros2/nav2/debug.md b/ros/ros2/nav2/debug.md new file mode 100644 index 0000000..eefcda3 --- /dev/null +++ b/ros/ros2/nav2/debug.md @@ -0,0 +1,211 @@ +``` bash +root@nvidia:~/ros2_ws# ros2 topic echo /goal_pose +header: + stamp: + sec: 1776912839 + nanosec: 772353086 + frame_id: map +pose: + position: + x: -0.2929971516132355 + y: -28.93631362915039 + z: 0.0 + orientation: + x: 0.0 + y: 0.0 + z: -0.7140266359687852 + w: 0.7001185350546718 +--- +header: + stamp: + sec: 1776912894 + nanosec: 349057427 + frame_id: map +pose: + position: + x: 1.0191293954849243 + y: -23.940237045288086 + z: 0.0 + orientation: + x: 0.0 + y: 0.0 + z: -0.758253550259611 + w: 0.6519597790651626 +--- +header: + stamp: + sec: 1776912930 + nanosec: 59193832 + frame_id: map +pose: + position: + x: -0.25821736454963684 + y: -26.604511260986328 + z: 0.0 + orientation: + x: 0.0 + y: 0.0 + z: -0.7286561115363753 + w: 0.6848797493872113 +--- +header: + stamp: + sec: 1776913007 + nanosec: 811936088 + frame_id: map +pose: + position: + x: -0.5403046607971191 + y: -23.95861053466797 + z: 0.0 + orientation: + x: 0.0 + y: 0.0 + z: -0.7323575592769619 + w: 0.6809202635917743 +--- +header: + stamp: + sec: 1776913105 + nanosec: 601216801 + frame_id: map +pose: + position: + x: -0.13717754185199738 + y: -31.840221405029297 + z: 0.0 + orientation: + x: 0.0 + y: 0.0 + z: -0.6531641242066932 + w: 0.7572163672618966 +--- + +``` + +雷达同步问题 +``` +ros2_ws\src\rslidar_sdk\config\config.yaml +use_lidar_clock: false +``` + + +``` + --- + ⚠️ 警告1:No goal checker was specified in parameter 'current_goal_checker'. Server will use only plugin loaded + general_goal_checker + + 含义 + + 这是配置缺失类警告,不影响功能,只是提示你没有显式指定当前使用的目标检查器,系统自动用了第一个加载的general_goal_check + er。 + 根因 + + ROS2 Humble及以上版本的Nav2新增了current_goal_checker强制配置项,你的配置里只定义了goal_checker插件,但没有指定当前使 + 用哪一个。 + ✅ 解决方案 + + 在controller_server的ros__parameters下添加一行即可: + controller_server: + ros__parameters: + current_goal_checker: "general_goal_checker" # 新增这行 + controller_frequency: 20.0 + # ... 其他原有配置 + + --- + ⚠️ 警告2:Behavior Tree tick rate 100.00 was exceeded! + + 含义 + + 这是性能类警告,行为树默认tick频率是100Hz(每10ms执行一次),现在单次tick执行时间超过了10ms,导致频率不达标。 + 根因 + + 行为树中的计算密集型节点执行太慢,90%的情况是MPPI控制器计算耗时过长,小概率是系统CPU负载过高、规划器卡顿等。 + ✅ 排查&解决方案 + + 1. 先看CPU占用:top 看controller_server进程的CPU占比,如果超过100%就是计算量太大 + 2. 优先优化MPPI参数(你的当前配置计算量过高),后面警告3会详细说 + 3. 实在优化不了可以调大BT的tick间隔,在bt_navigator下加: + bt_navigator: + ros__parameters: + bt_loop_duration: 20 # 从10ms改成20ms,频率降到50Hz,不推荐,优先优化控制器 + + --- + ⚠️ 警告3:Control loop missed its desired rate of 20.0000Hz + + 含义 + + 这是核心性能警告,控制器要求20Hz的控制频率(每50ms输出一次速度指令),现在单次循环执行超过了50ms,频率不达标。 + ⚠️ 这个问题必须优先解决:控制频率低于15Hz会导致MPPI控制不稳定,甚至出现急刹、撞障碍物的情况。 + 根因 + + 你的MPPI配置计算量过大,两个核心参数超标: + FollowPath: + batch_size: 2000 # 单次迭代采样2000条轨迹,计算量极大 + time_steps: 56 # 每条轨迹预测56步(0.05*56=2.8秒预测时长) + - 2000的batch_size在Jetson NX级别的嵌入式平台单次计算就要60-80ms,肯定达不到50ms的要求 + - 额外加重负载的配置:local costmap的obstacle_max_range: 20.0,local + costmap本身只有6m×6m,处理20米内的点云完全是浪费CPU + ✅ 解决方案(按优先级) + + 1. 调小MPPI计算量(优先保证控制频率达标): + FollowPath: + batch_size: 1000 # 降到800-1200,轨迹采样数减半,性能提升一倍,效果下降不明显 + time_steps: 40 # 降到32-40,预测时长2秒足够,履带车速度慢不需要太长预测 + 2. 缩小local costmap障碍物检测范围: + # local_costmap的voxel_layer下的scan配置 + obstacle_max_range: 10.0 # 从20米改成10米,足够覆盖6m的local costmap范围 + 3. 验证效果:改完后用ros2 topic hz /cmd_vel_nav看频率,稳定在18Hz以上就算合格 + + --- + ❌ 错误1:Failed to create a plan from potential when a legal potential was found. This shouldn't happen. + + 含义 + + 这是Navfn规划器内部错误:规划器已经算出了从起点到终点的势场(理论上存在可行路径),但实际提取路径的时候失败了。 + 根因 + + 结合你的配置,最可能的几个原因: + 4. 可行通道太窄:你的膨胀半径是1.8m,车身本身宽1.8m,通道宽度必须大于3.6m才能通过,如果路径上有窄于这个宽度的通道,膨 + 胀后就没有可行空间了 + 5. 起点/终点落在膨胀区内:虽然势场是通的,但膨胀后的代价太高,路径提取的时候找不到合法的起点/终点 + 6. 膨胀半径过大:1.8m的膨胀半径刚好是车身宽度,没有冗余,稍微有点障碍物就会把通道堵死 + 7. 全局costmap噪点过多:点云误检的障碍物挡住了路径 + ✅ 排查&解决方案 + + 8. 排查路径情况:规划失败时,在rviz上看起点到终点的通道宽度,是不是小于3.6m + 9. 优化膨胀半径(如果通道普遍较窄): + # 全局和局部costmap的inflation_radius都可以降到1.5m(只要大于车身最大半长1.2m就满足SMAC优化要求) + inflation_radius: 1.5 + 10. 优化Navfn参数: + GridBased: + tolerance: 1.0 # 从0.5米改成1.0米,允许终点有更大的容忍范围 + 11. 终极方案:换规划器:如果经常走窄通道,把Navfn换成nav2_smac_planner/SmacPlanner,对窄通道的支持好很多 + 12. 检查全局costmap噪点:如果有很多误检的小障碍物,调大mark_threshold过滤噪点 + + --- + ❌ 错误2:Failed to get result for follow_path in node halt! + + 含义 + + 这是次生错误,不影响功能,只是日志提示:行为树在终止(halt)的时候,尝试获取follow_path节点的执行结果,但结果不存在。 + 根因 + + 完全是前面的规划失败导致的连锁反应:规划失败后整个导航任务提前终止,follow_path节点还没来得及产生结果就被强制停止了。 + ✅ 解决方案 + + 解决前面的规划失败问题后,这个错误会自动消失,不需要单独处理。 + + --- + 🎯 解决优先级建议 + + 13. 【最高优先级】先解决控制循环频率不够的问题,直接影响导航安全性 + 14. 【次高优先级】解决规划失败的问题,影响导航可用性 + 15. 【低优先级】解决剩下的配置类警告,不影响功能只是优化日志 + + 额外优化建议 + + 你现在的voxel层mark_threshold: 10有点太高了,需要10个点才能标记障碍物,容易漏检小障碍物,建议调到3-5更合适: + voxel_layer: + mark_threshold: 3 # 从10改成3,平衡噪点过滤和小障碍物检测 +``` \ No newline at end of file diff --git a/ros/ros2/nav2/nav2.md b/ros/ros2/nav2/nav2.md new file mode 100644 index 0000000..e69de29 diff --git a/ros/ros2/nav2/nav2_bringup_gps_demo.md b/ros/ros2/nav2/nav2_bringup_gps_demo.md new file mode 100644 index 0000000..b4fdae2 --- /dev/null +++ b/ros/ros2/nav2/nav2_bringup_gps_demo.md @@ -0,0 +1,356 @@ +# Navigation2 详解:nav2_bringup 与 nav2_gps_waypoint_follower_demo + +## 1. Navigation2 整体介绍 +Navigation2(简称Nav2)是ROS2生态中最成熟的开源导航框架,是ROS1 Navigation Stack的官方继任者,专为移动机器人自主导航设计。 + +### 1.1 核心功能 +- **定位**:支持AMCL、SLAM(Cartographer、SLAM Toolbox等)、GPS/RTK等多源定位 +- **全局路径规划**:支持A*、Dijkstra、NavFn等多种规划算法 +- **局部路径跟踪**:支持DWA、TEB、MPPI、Pure Pursuit等跟踪算法 +- **避障与行为树**:通过行为树实现复杂导航逻辑,支持动态障碍物规避 +- **重规划与恢复行为**:导航失败时自动执行恢复策略(旋转、回退、清图等) +- **多机器人支持**:支持命名空间隔离的多机器人导航 + +### 1.2 整体架构 +Nav2采用模块化插件式设计,核心模块包括: +``` +├── 感知层 +│ ├── 传感器数据处理(LiDAR、Camera、IMU、GPS等) +│ └── 障碍物检测/语义分割 +├── 定位层 +│ ├── AMCL(蒙特卡洛定位) +│ ├── SLAM 建图 +│ └── 多传感器融合定位 +├── 地图层 +│ ├── 代价地图(全局/局部) +│ ├── 图层插件(静态层、障碍层、膨胀层、社会层等) +├── 规划层 +│ ├── 全局路径规划器 +│ └── 平滑器 +├── 控制层 +│ ├── 局部路径规划器 +│ └── 轨迹跟踪控制器 +├── 行为决策层 +│ ├── 行为树执行器 +│ └── 恢复行为管理器 +└── 接口层 + ├── RViz 可视化 + ├── Action/Topic API + └── 配置参数系统 +``` + +--- + +## 2. nav2_bringup 包详解 +nav2_bringup是Nav2的官方启动集成包,提供了开箱即用的启动文件、配置模板和参数集合,是快速部署Nav2系统的入口。 + +### 2.1 代码结构 +``` +nav2_bringup/ +├── bringup/ # 启动相关核心目录 +│ ├── launch/ # 启动文件集合 +│ │ ├── bringup_launch.py # 主启动文件,集成所有导航模块 +│ │ ├── localization_launch.py # 单独启动定位模块(AMCL/SLAM) +│ │ ├── navigation_launch.py # 单独启动导航模块(规划/控制/行为树) +│ │ ├── rviz_launch.py # 启动RViz可视化 +│ │ ├── slam_launch.py # 启动SLAM建图 +│ │ └── urdf_launch.py # 加载机器人URDF模型 +│ ├── params/ # 参数配置文件目录 +│ │ ├── nav2_params.yaml # 导航全模块默认参数 +│ │ ├── nav2_params_no_odom.yaml # 无里程计场景参数 +│ │ ├── nav2_slam_params.yaml # SLAM模式参数 +│ │ └── robot_localization/ # 传感器融合参数模板 +│ └── rviz/ # RViz配置文件 +│ └── nav2_default_view.rviz # Nav2默认RViz配置 +├── docker/ # Docker部署相关文件 +├── scripts/ # 辅助脚本 +├── CMakeLists.txt +├── package.xml +└── README.md +``` + +### 2.2 核心启动文件说明 + +#### 2.2.1 bringup_launch.py +这是最常用的一站式启动文件,集成了完整的导航流程,支持参数配置: +```python +# 关键参数 +'namespace': '', # 多机器人命名空间 +'use_sim_time': False, # 是否使用仿真时间 +'rviz_config_file': '', # RViz配置文件路径 +'params_file': '', # 导航参数文件路径 +'autostart': True, # 启动后自动激活导航栈 +'use_composition': True, # 使用组件化节点(减少进程数,提高性能) +'use_respawn': False, # 节点崩溃时自动重启 +'map': '', # 静态地图文件路径(.yaml/.pgm) +'slam': False, # 是否启用SLAM模式 +'localization_type': 'amcl' # 定位方式:amcl/slam_toolbox等 +``` +启动示例: +```bash +# 仿真环境启动导航 +ros2 launch nav2_bringup bringup_launch.py use_sim_time:=True map:=/path/to/map.yaml + +# 真机环境启用SLAM建图 +ros2 launch nav2_bringup bringup_launch.py slam:=True params_file:=/path/to/my_params.yaml +``` + +#### 2.2.2 localization_launch.py +单独启动定位模块,适合只需要定位不需要完整导航的场景: +```bash +# 仅启动AMCL定位 +ros2 launch nav2_bringup localization_launch.py map:=/path/to/map.yaml use_sim_time:=True +``` + +#### 2.2.3 navigation_launch.py +单独启动导航模块(规划/控制/行为树),适合定位已由其他系统提供的场景: +```bash +# 仅启动导航模块,使用已有的定位信息 +ros2 launch nav2_bringup navigation_launch.py params_file:=/path/to/my_params.yaml +``` + +### 2.3 配置文件详解 +nav2_params.yaml是核心参数配置文件,采用分层结构,每个模块单独配置: +```yaml +amcl: + ros__parameters: + base_frame_id: "base_footprint" # 机器人基坐标系 + global_frame_id: "map" # 全局坐标系 + odom_frame_id: "odom" # 里程计坐标系 + max_particles: 2000 # 最大粒子数 + min_particles: 500 # 最小粒子数 + update_min_a: 0.2 # 角度变化超过0.2rad时更新 + update_min_d: 0.25 # 位移超过0.25m时更新 + +bt_navigator: + ros__parameters: + use_sim_time: False + bt_xml_filename: "navigate_w_replanning_and_recovery.xml" # 行为树文件 + +global_costmap: + global_costmap: + ros__parameters: + update_frequency: 1.0 + publish_frequency: 1.0 + global_frame: map + robot_base_frame: base_footprint + resolution: 0.05 + plugins: + - {name: static_layer, type: "costmap_2d::StaticLayer"} + - {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"} + - {name: inflation_layer, type: "costmap_2d::InflationLayer"} + +local_costmap: + local_costmap: + ros__parameters: + update_frequency: 5.0 + publish_frequency: 2.0 + global_frame: odom + robot_base_frame: base_footprint + width: 3 + height: 3 + resolution: 0.05 + rolling_window: true # 局部代价地图随机器人移动 + +planner_server: + ros__parameters: + expected_planner_frequency: 1.0 + planner_plugins: ["GridBased"] + GridBased: + plugin: "nav2_navfn_planner/NavfnPlanner" # 默认使用NavFn规划器 + use_astar: true # 启用A*算法 + +controller_server: + ros__parameters: + controller_frequency: 20.0 + min_x_velocity_threshold: 0.001 + min_y_velocity_threshold: 0.5 + controller_plugins: ["FollowPath"] + FollowPath: + plugin: "nav2_regulated_pure_pursuit_controller/RegulatedPurePursuitController" # 默认使用Pure Pursuit控制器 +``` + +### 2.4 最佳实践 +1. **不要直接修改默认参数文件**:将nav2_params.yaml复制到自己的工作空间进行修改,通过`params_file`参数传入 +2. **组件化启动**:默认启用`use_composition:=True`可以显著减少内存占用和通信开销 +3. **分层配置**:将通用参数和机器人特定参数分开存放,便于维护 +4. **仿真与真机分离**:使用`use_sim_time`参数区分仿真和真机环境,分别配置不同的参数值 + +--- + +## 3. nav2_gps_waypoint_follower_demo 详解 +这是Nav2官方提供的室外导航示例,演示了如何结合GPS/RTK定位实现全局航点跟随功能,适用于无人车、巡检机器人等室外场景。 + +### 3.1 代码结构 +该包位于navigation2_tutorials仓库中,结构如下: +``` +nav2_gps_waypoint_follower_demo/ +├── bringup/ +│ ├── launch/ +│ │ ├── gps_waypoint_follower_launch.py # Demo主启动文件 +│ │ ├── rviz.launch.py # RViz启动 +│ │ └── dual_ekf.launch.py # 双EKF传感器融合启动 +│ ├── params/ +│ │ ├── dual_ekf.yaml # 传感器融合参数 +│ │ ├── nav2_params.yaml # 导航参数(适配GPS场景) +│ │ └── waypoint_follower_params.yaml # 航点跟随器参数 +│ ├── rviz/ +│ │ └── gps_waypoint.rviz # GPS导航专用RViz配置 +│ └── worlds/ +│ └── gps_world.world # 仿真世界文件(含GPS插件) +├── config/ +│ └── sample_waypoints.yaml # 示例航点配置文件 +├── src/ +│ └── gps_waypoint_logger.cpp # 航点到达日志节点(可选) +├── CMakeLists.txt +├── package.xml +└── README.md +``` + +### 3.2 核心组件说明 +GPS航点跟随系统主要由三个核心部分组成: +1. **传感器融合模块**(robot_localization):融合GPS、IMU、轮式里程计数据,输出全局定位 +2. **导航栈模块**:基于全局定位进行路径规划和跟踪 +3. **航点跟随器**:按照预设的GPS航点序列依次导航 + +#### 3.2.1 双EKF传感器融合 +demo使用两个扩展卡尔曼滤波器(EKF)实现多传感器融合: +```yaml +# dual_ekf.yaml 核心配置 +ekf_filter_node_odom: + ros__parameters: + frequency: 30.0 + sensor_timeout: 0.1 + two_d_mode: true + publish_tf: true + odom_frame: odom + base_link_frame: base_link + world_frame: odom + # 融合IMU和轮式里程计,输出odom->base_link变换 + imu0: /imu/data + odom0: /wheel/odometry + +ekf_filter_node_map: + ros__parameters: + frequency: 30.0 + sensor_timeout: 0.1 + two_d_mode: true + publish_tf: true + odom_frame: odom + base_link_frame: base_link + world_frame: map + # 融合GPS数据,输出map->odom变换 + odom1: /gps/fix + odom1_differential: false + odom1_relative: false +``` +- 第一个EKF(odom系):融合IMU和轮式里程计,提供短时间内高精度的局部定位,无漂移 +- 第二个EKF(map系):融合GPS数据,提供全局绝对定位,修正长期漂移 + +#### 3.2.2 导航参数适配(nav2_params.yaml) +GPS导航场景需要对默认导航参数进行调整: +```yaml +amcl: + ros__parameters: + # GPS导航场景下禁用AMCL,使用EKF融合提供定位 + use_sim_time: False + # AMCL相关参数全部注释或删除 + +global_costmap: + global_costmap: + ros__parameters: + # GPS模式下不使用静态地图,使用动态生成的代价地图 + plugins: + - {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"} + - {name: inflation_layer, type: "costmap_2d::InflationLayer"} + # 代价地图大小足够覆盖所有航点范围 + width: 1000 + height: 1000 + resolution: 0.1 + rolling_window: false # 全局代价地图固定,不随机器人移动 + origin_x: -500 + origin_y: -500 + +planner_server: + ros__parameters: + # 使用适合长距离规划的算法 + GridBased: + plugin: "nav2_navfn_planner/NavfnPlanner" + use_astar: true + allow_unknown: true # 允许在未知区域规划路径 + +controller_server: + ros__parameters: + # 使用适合高速行驶的控制器 + FollowPath: + plugin: "nav2_mppi_controller/MPPIController" # 或者TEB控制器 + max_vel_x: 5.0 # 室外场景允许更高速度 +``` + +#### 3.2.3 航点跟随器配置 +```yaml +# waypoint_follower_params.yaml +waypoint_follower: + ros__parameters: + loop: False # 航点是否循环执行 + waypoint_timeout: 300.0 # 单个航点导航超时时间(秒) + stop_on_failure: True # 某个航点导航失败时停止 + action_server_name: "follow_waypoints" + # 航点到达阈值 + goal_tolerance_x: 0.5 + goal_tolerance_y: 0.5 + goal_tolerance_yaw: 0.25 +``` + +### 3.3 航点配置 +sample_waypoints.yaml是预设的GPS航点文件,格式如下: +```yaml +waypoints: + - latitude: 37.7749 + longitude: -122.4194 + yaw: 0.0 # 到达后的朝向(弧度) + frame_id: "wgs84" # GPS坐标系 + - latitude: 37.7750 + longitude: -122.4195 + yaw: 1.57 + frame_id: "wgs84" + - latitude: 37.7751 + longitude: -122.4196 + yaw: 3.14 + frame_id: "wgs84" +``` +航点使用WGS84坐标系(标准GPS坐标),也可以配置为UTM坐标系。 + +### 3.4 运行流程 +1. **启动仿真/真机驱动**:加载机器人模型、传感器驱动、GPS插件 +2. **启动传感器融合**:`ros2 launch nav2_gps_waypoint_follower_demo dual_ekf.launch.py` +3. **启动导航栈**:`ros2 launch nav2_gps_waypoint_follower_demo gps_waypoint_follower_launch.py` +4. **加载航点**:`ros2 run nav2_waypoint_follower waypoint_follower --ros-args -p waypoint_file:=/path/to/sample_waypoints.yaml` +5. **启动航点跟随**:通过RViz发送FollowWaypoints action请求,或者用命令行启动: + ```bash + ros2 action send_goal /follow_waypoints nav2_msgs/action/FollowWaypoints "{waypoints: []}" + ``` + +### 3.5 关键注意事项 +1. **GPS信号质量**:室外场景下需要确保GPS信号良好,RTK定位能达到厘米级精度,普通GPS只有米级精度,可能影响导航效果 +2. **坐标系转换**:需要正确配置WGS84到UTM再到机器人本地坐标系的转换参数 +3. **航点规划**:航点之间需要有可行路径,避免有障碍物阻挡 +4. **动态障碍物**:室外场景需要配置合适的障碍物检测和避障参数 +5. **TF树检查**:确保`map->odom->base_link`的TF变换正确发布,这是GPS导航的基础 + +--- + +## 4. 常用调试技巧 +1. **查看TF树**:`ros2 run tf2_tools view_frames`,检查坐标系变换是否正确 +2. **检查定位质量**:`ros2 topic echo /gps/fix` 查看GPS信号质量,`ros2 topic echo /odometry/filtered` 查看融合后的定位输出 +3. **可视化调试**:在RViz中显示全局/局部代价地图、规划路径、当前目标点等信息 +4. **参数动态调整**:使用`ros2 param`命令动态修改参数,无需重启导航栈 +5. **日志分析**:查看`/tf`, `/cmd_vel`, `/plan`等话题的输出,排查导航失败原因 + +--- + +## 参考资料 +- [Navigation2 官方文档](https://navigation.ros.org/) +- [nav2_bringup 源码](https://github.com/ros-navigation/navigation2/tree/main/nav2_bringup) +- [GPS Waypoint Follower 教程](https://navigation.ros.org/tutorials/docs/gps_waypoint_follower.html) +- [navigation2_tutorials 仓库](https://github.com/ros-navigation/navigation2_tutorials) diff --git a/ros/ros2/ros2_control/环境.md b/ros/ros2/ros2_control/环境.md new file mode 100644 index 0000000..3c18551 --- /dev/null +++ b/ros/ros2/ros2_control/环境.md @@ -0,0 +1,59 @@ +#### 拉取镜像 +```bash +docker pull arm64v8/ros:humble +``` + +#### 启动脚本 +```code +#!/bin/bash + +# 允许 Docker 访问 X 服务器(用于 GUI) +xhost +local:docker + +# 容器名称 +CONTAINER_NAME="ylhan_ros2_humble" + +# 检查容器是否存在 +if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + # 容器存在 + if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then + # 容器正在运行,直接进入 + echo "容器 ${CONTAINER_NAME} 正在运行,进入容器..." + docker exec -it ${CONTAINER_NAME} bash + else + # 容器已存在但未运行,启动并进入 + echo "容器 ${CONTAINER_NAME} 已存在但未运行,启动容器..." + docker start -i ${CONTAINER_NAME} + fi +else + # 容器不存在,创建并运行新容器 + echo "容器 ${CONTAINER_NAME} 不存在,创建新容器..." + docker run -it --rm \ + --name ${CONTAINER_NAME} \ + --network host \ + --privileged \ + -e DISPLAY=$DISPLAY \ + -v /tmp/.X11-unix:/tmp/.X11-unix:rw \ + -v /home/ylhan/ros2_ws:/root/ros2_ws \ + -v /dev:/dev \ + arm64v8/ros:humble \ + bash +fi + +``` + +#### 环境设置 +宿主机 +```bash +echo $DISPLAY +``` +假设输出为nvidia:13.0,在docker内: +```bash +export DISPLAY=nvidia:13.0 +``` +复制宿主机home目录下.Xauthority文件到docker中home目录下,使用xeyes测试 + +ros2 docker隔离 +```bash +export ROS_DOMAIN_ID=79 #设置独立的DOMAIN_ID +``` \ No newline at end of file diff --git a/ros/ros2/安装配置/ros2_structure.md b/ros/ros2/安装配置/ros2_structure.md new file mode 100644 index 0000000..e7d6912 --- /dev/null +++ b/ros/ros2/安装配置/ros2_structure.md @@ -0,0 +1,128 @@ +# ROS2 代码结构图 + +## ROS2 工作区目录结构 + +```mermaid +flowchart TD + Workspace[ROS2 工作区] --> src[src/ 源代码目录] + Workspace --> build[build/ 构建目录] + Workspace --> install[install/ 安装目录] + Workspace --> log[log/ 日志目录] + + src --> Package1[包1] + src --> Package2[包2] + src --> PackageN[...] + + Package1 --> P1_CMake[CMakeLists.txt] + Package1 --> P1_PackageXML[package.xml] + Package1 --> P1_src[src/ 源代码] + Package1 --> P1_include[include/ 头文件] + Package1 --> P1_msgs[msg/ 消息定义] + Package1 --> P1_srvs[srv/ 服务定义] + Package1 --> P1_actions[action/ 动作定义] +``` + +## ROS2 软件架构 + +```mermaid +flowchart TD + App[应用程序] --> ClientLibs[客户端库] + + subgraph ClientLibs [客户端库] + direction LR + RCLcpp[C++ 客户端库 rclcpp] + RCLpy[Python 客户端库 rclpy] + RCL[C 客户端库 rcl] + end + + ClientLibs --> RCL_Interface[RCL 接口] + RCL_Interface --> RMW[ROS 中间件接口 RMW] + + subgraph DDS_Implementations [DDS 实现] + direction LR + FastDDS[Fast DDS] + CycloneDDS[Cyclone DDS] + RTI_Connext[RTI Connext] + OpenSplice[OpenSplice] + end + + RMW --> DDS_Implementations + DDS_Implementations --> Network[网络通信] +``` + +## ROS2 核心包依赖关系 + +```mermaid +flowchart TD + ROS2_Core[ROS2 核心] --> ament_core[ament_core
构建系统] + ROS2_Core --> rcl[rcl
C语言客户端库] + ROS2_Core --> rclcpp[rclcpp
C++客户端库] + ROS2_Core --> rclpy[rclpy
Python客户端库] + + rcl --> rmw[rmw
中间件接口] + rclcpp --> rcl + rclpy --> rcl + + rmw --> rmw_implementation[rmw_implementation
中间件实现] + rmw_implementation --> DDS[DDS 实现] + + ROS2_Tools[ROS2 工具] --> ros2cli[ros2cli
命令行工具] + ROS2_Tools --> colcon[colcon
构建工具] + ROS2_Tools --> launch_ros[launch_ros
启动系统] +``` + +## ROS2 节点通信模型 + +```mermaid +flowchart LR + NodeA[ROS2 节点 A] -->|发布话题| Topic1[话题 /topic1] + NodeB[ROS2 节点 B] -->|订阅话题| Topic1 + + NodeC[ROS2 节点 C] -->|请求服务| Service1[服务 /service1] + NodeD[ROS2 节点 D] -->|提供服务| Service1 + + NodeE[ROS2 节点 E] -->|发送目标| Action1[动作 /action1] + NodeF[ROS2 节点 F] -->|执行动作| Action1 + NodeF -->|反馈| NodeE + NodeF -->|结果| NodeE +``` + +## 说明 + +### 1. 工作区目录结构 +- **src/**: 包含所有ROS2包的源代码 +- **build/**: 构建过程中生成的中间文件 +- **install/**: 安装目录,包含可执行文件、库和资源 +- **log/**: 构建和运行时的日志文件 + +### 2. ROS2包的基本结构 +每个ROS2包通常包含: +- `CMakeLists.txt`: CMake构建配置文件 +- `package.xml`: 包元数据文件 +- `src/`: C++或Python源代码 +- `include/`: C++头文件 +- `msg/`, `srv/`, `action/`: 消息、服务、动作定义文件 + +### 3. 软件架构层次 +1. **应用程序层**: 用户编写的ROS2节点 +2. **客户端库层**: 语言特定的API(C++、Python、C) +3. **RCL层**: 通用的ROS客户端库 +4. **RMW层**: ROS中间件抽象接口 +5. **DDS层**: 具体的DDS实现 + +### 4. 通信模式 +- **话题(Topics)**: 发布/订阅模式,单向异步通信 +- **服务(Services)**: 请求/响应模式,同步通信 +- **动作(Actions)**: 目标/反馈/结果模式,长时间运行的任务 + +## 使用方法 + +1. 将本文件在支持 Mermaid 图的 Markdown 查看器中打开(如 VS Code with Mermaid 插件、GitHub、GitLab 等) +2. 图表将自动渲染为可视化图形 +3. 如需修改图表,编辑对应的 Mermaid 代码块 + +## 相关资源 + +- [ROS2 官方文档](https://docs.ros.org/) +- [ROS2 架构设计](https://design.ros2.org/) +- [Mermaid 语法指南](https://mermaid.js.org/syntax/flowchart.html) \ No newline at end of file diff --git a/ros/ros2/安装配置/代码更新_zh.md b/ros/ros2/安装配置/代码更新_zh.md new file mode 100644 index 0000000..c1629dd --- /dev/null +++ b/ros/ros2/安装配置/代码更新_zh.md @@ -0,0 +1,77 @@ +# 维护 ROS 2 源代码检出 + +## [概述](https://docs.ros.org/en/humble/Installation/Maintaining-a-Source-Checkout.html) + +本文档介绍如何维护从源代码构建的 ROS 2 安装。如果您已经从源代码安装了 ROS 2,并且想要更新到最新的错误修复和功能,请遵循本指南。 + +## [更新 ROS 2 源代码](https://docs.ros.org/en/humble/Installation/Maintaining-a-Source-Checkout.html#updating-ros-2-source-code) + +### 1. 更新仓库列表文件 + +首先,您需要获取最新的 `ros2.repos` 文件,该文件定义了构建 ROS 2 所需的所有仓库及其分支。 + +```bash +# 对于 Humble Hawksbill 版本 +cd ~/ros2_humble +wget https://raw.githubusercontent.com/ros2/ros2/humble/ros2.repos -O ros2.repos +``` + +或者,如果您想使用特定分支(例如主分支)而不是发布分支: + +```bash +# 使用主分支(开发版本) +wget https://raw.githubusercontent.com/ros2/ros2/master/ros2.repos -O ros2.repos +``` + +### 2. 更新本地仓库 + +使用 `vcs` 工具更新您的本地仓库: + +```bash +# 更新所有仓库的远程引用 +vcs custom --args remote update +``` + +### 3. 下载新的源代码 + +现在,使用新的 `ros2.repos` 文件导入并拉取最新的代码: + +```bash +# 导入新仓库定义 +vcs import src < ros2.repos + +# 拉取所有仓库的最新代码 +vcs pull src +``` + +**注意**:`vcs import` 命令将覆盖 `src` 目录中现有的仓库定义。如果您有本地修改或添加了额外的仓库,请确保在运行此命令之前备份您的更改。 + +### 4. 重新构建工作空间 + +更新源代码后,需要重新构建工作空间: + +```bash +# 返回到工作空间根目录 +cd ~/ros2_humble + +# 使用 colcon 重新构建 +colcon build --symlink-install +``` + +构建选项说明: +- `--symlink-install`:使用符号链接而不是复制文件,这可以加快构建速度并减少磁盘空间使用 + +### 5. 检查源代码状态 + +要查看当前工作空间中所有仓库的状态,可以导出当前的仓库配置: + +```bash +# 导出当前仓库状态 +vcs export src > my_ros2.repos +``` + +这将在当前目录下创建一个 `my_ros2.repos` 文件,其中包含所有仓库的当前提交哈希值。您可以将此文件用于: +- 备份当前的源代码状态 +- 在其他机器上复制相同的配置 +- 调试构建问题 + diff --git a/ros/ros2/安装配置/安装.md b/ros/ros2/安装配置/安装.md new file mode 100644 index 0000000..133d0aa --- /dev/null +++ b/ros/ros2/安装配置/安装.md @@ -0,0 +1,137 @@ +## [System requirements](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id1)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#system-requirements "Link to this heading") + +The current Debian-based target platforms for Humble Hawksbill are: + +- Tier 1: Ubuntu Linux - Jammy (22.04) 64-bit + +- Tier 3: Ubuntu Linux - Focal (20.04) 64-bit + +- Tier 3: Debian Linux - Bullseye (11) 64-bit + + +Other Linux platforms with varying support levels include: + +- Arch Linux, see [alternate instructions](https://wiki.archlinux.org/index.php/ROS#ROS_2) + +- Fedora Linux, see [alternate instructions](https://ros2docs.robook.org/humble/Installation/Alternatives/Fedora-Development-Setup.html) + +- OpenEmbedded / webOS OSE, see [alternate instructions](https://github.com/ros/meta-ros/wiki/OpenEmbedded-Build-Instructions) + + +As defined in [REP 2000](https://www.ros.org/reps/rep-2000.html). + +## [System setup](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id2)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#system-setup "Link to this heading") + +### [Set locale](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id3)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#set-locale "Link to this heading") + +请确保您有一个支持 `UTF-8` 的区域设置。 如果您处于最简环境中(例如 docker 容器),区域设置可能是一些类似 `POSIX` 的选项。 我们使用以下设置通过了测试。但是,如果您使用不同的支持 `UTF-8` 的区域设置,也应该没问题。 + +`locale # check for UTF-8` +`sudo apt update && sudo apt install locales` +`sudo locale-gen en_US en_US.UTF-8` +`sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8` +`export LANG=en_US.UTF-8` +`locale # verify settings` + +### [Add the ROS 2 apt repository](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id4)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#add-the-ros-2-apt-repository "Link to this heading") + +你需要将 ROS 2 apt 仓库添加到你的系统中。 + +首先确保 [Ubuntu Universe 仓库](https://help.ubuntu.com/community/Repositories/Ubuntu) 已启用。 + +`sudo apt install software-properties-common` +`sudo add-apt-repository universe` + +然后使用 apt 添加 ROS 2 GPG 密钥。 + +`sudo apt update && sudo apt install curl -y` +`sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg` + +然后将仓库添加到你的源列表中。 + +`echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null` + +### [Install development tools and ROS tools](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id5)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#install-development-tools-and-ros-tools "Link to this heading") + +Install common packages. + +`sudo apt update && sudo apt install -y \` + `python3-flake8-docstrings \` + `python3-pip \` + `python3-pytest-cov \` + `ros-dev-tools` + +Install packages according to your Ubuntu version. + +Ubuntu 22.04 LTS and laterUbuntu 20.04 LTS + +`sudo apt install -y \` + `python3-flake8-blind-except \` + `python3-flake8-builtins \` + `python3-flake8-class-newline \` + `python3-flake8-comprehensions \` + `python3-flake8-deprecated \` + `python3-flake8-import-order \` + `python3-flake8-quotes \` + `python3-pytest-repeat \` + `python3-pytest-rerunfailures` + +## [Get ROS 2 code](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id6)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#get-ros-2-code "Link to this heading") + +Create a workspace and clone all repos: + +`mkdir -p ~/ros2_humble/src` +`cd ~/ros2_humble` +`vcs import --input https://raw.githubusercontent.com/ros2/ros2/humble/ros2.repos src` + +## [Install dependencies using rosdep](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id7)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#install-dependencies-using-rosdep "Link to this heading") + +ROS 2 包是在经常更新的 Ubuntu 系统上构建的。 在安装新包之前,建议您确保系统是最新的。 + +%% `sudo apt upgrade` %% + +`sudo rosdep init` +`rosdep update` +`rosdep install --from-paths src --ignore-src -y --skip-keys "fastcdr rti-connext-dds-6.0.1 urdfdom_headers"` + +**Note**: If you’re using a distribution that is based on Ubuntu (like Linux Mint) but does not identify itself as such, you’ll get an error message like `Unsupported OS [mint]`. In this case append `--os=ubuntu:jammy` to the above command. + +## [Install additional DDS implementations (optional)](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id8)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#install-additional-dds-implementations-optional "Link to this heading") + +If you would like to use another DDS or RTPS vendor besides the default, you can find instructions [here](https://ros2docs.robook.org/humble/Installation/DDS-Implementations.html). + +## [Build the code in the workspace](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id9)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#build-the-code-in-the-workspace "Link to this heading") + +If you have already installed ROS 2 another way (either via debs or the binary distribution), make sure that you run the below commands in a fresh environment that does not have those other installations sourced. Also ensure that you do not have `source /opt/ros/${ROS_DISTRO}/setup.bash` in your `.bashrc`. You can make sure that ROS 2 is not sourced with the command `printenv | grep -i ROS`. The output should be empty. + +More info on working with a ROS workspace can be found in [this tutorial](https://ros2docs.robook.org/humble/Tutorials/Beginner-Client-Libraries/Colcon-Tutorial.html). + +`cd ~/ros2_humble/` +`colcon build --symlink-install` + +Note: if you are having trouble compiling all examples and this is preventing you from completing a successful build, you can use `COLCON_IGNORE` in the same manner as [CATKIN_IGNORE](https://github.com/ros-infrastructure/rep/blob/master/rep-0128.rst) to ignore the subtree or remove the folder from the workspace. Take for instance: you would like to avoid installing the large OpenCV library. Well then simply run `touch COLCON_IGNORE` in the `cam2image` demo directory to leave it out of the build process. + +## [Environment setup](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id10)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#environment-setup "Link to this heading") + +### [Source the setup script](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id11)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#source-the-setup-script "Link to this heading") + +Set up your environment by sourcing the following file. + +# Replace ".bash" with your shell if you're not using bash +# Possible values are: setup.bash, setup.sh, setup.zsh + +`. ~/ros2_humble/install/local_setup.bash` + +## [Try some examples](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id12)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#try-some-examples "Link to this heading") + +In one terminal, source the setup file and then run a C++ `talker`: + +`. ~/ros2_humble/install/local_setup.bash` +`ros2 run demo_nodes_cpp talker` + +In another terminal source the setup file and then run a Python `listener`: + +`. ~/ros2_humble/install/local_setup.bash` +`ros2 run demo_nodes_py listener` + +You should see the `talker` saying that it’s `Publishing` messages and the `listener` saying `I heard` those messages. This verifies both the C++ and Python APIs are working properly. Hooray! \ No newline at end of file diff --git a/ros/ros2/安装配置/安装_zh.md b/ros/ros2/安装配置/安装_zh.md new file mode 100644 index 0000000..1693259 --- /dev/null +++ b/ros/ros2/安装配置/安装_zh.md @@ -0,0 +1,161 @@ +## [系统要求](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id1)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#system-requirements "Link to this heading") + +当前 Humble Hawksbill 基于 Debian 的目标平台包括: + +- 第一级:Ubuntu Linux - Jammy (22.04) 64位 + +- 第三级:Ubuntu Linux - Focal (20.04) 64位 + +- 第三级:Debian Linux - Bullseye (11) 64位 + + +其他支持程度不同的 Linux 平台包括: + +- Arch Linux,请参阅[替代安装说明](https://wiki.archlinux.org/index.php/ROS#ROS_2) + +- Fedora Linux,请参阅[替代安装说明](https://ros2docs.robook.org/humble/Installation/Alternatives/Fedora-Development-Setup.html) + +- OpenEmbedded / webOS OSE,请参阅[替代安装说明](https://github.com/ros/meta-ros/wiki/OpenEmbedded-Build-Instructions) + + +如 [REP 2000](https://www.ros.org/reps/rep-2000.html) 中所定义。 + +## [系统设置](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id2)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#system-setup "Link to this heading") + +### [设置区域](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id3)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#set-locale "Link to this heading") + +请确保您有一个支持 `UTF-8` 的区域设置。如果您处于最简环境中(例如 docker 容器),区域设置可能是一些类似 `POSIX` 的选项。我们使用以下设置通过了测试。但是,如果您使用不同的支持 `UTF-8` 的区域设置,也应该没问题。 + +```bash +locale # 检查 UTF-8 支持 +sudo apt update && sudo apt install locales +sudo locale-gen en_US en_US.UTF-8 +sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 +export LANG=en_US.UTF-8 +locale # 验证设置 +``` + +### [添加 ROS 2 apt 仓库](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id4)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#add-the-ros-2-apt-repository "Link to this heading") + +你需要将 ROS 2 apt 仓库添加到你的系统中。 + +首先确保 [Ubuntu Universe 仓库](https://help.ubuntu.com/community/Repositories/Ubuntu) 已启用。 + +```bash +sudo apt install software-properties-common +sudo add-apt-repository universe +``` + +然后使用 apt 添加 ROS 2 GPG 密钥。 + +```bash +sudo apt update && sudo apt install curl -y +sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg +``` + +然后将仓库添加到你的源列表中。 + +```bash +echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null +``` + +### [安装开发工具和 ROS 工具](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id5)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#install-development-tools-and-ros-tools "Link to this heading") + +安装常用软件包。 + +```bash +sudo apt update && sudo apt install -y \ + python3-flake8-docstrings \ + python3-pip \ + python3-pytest-cov \ + ros-dev-tools +``` + +根据您的 Ubuntu 版本安装软件包。 + +Ubuntu 22.04 LTS 及更高版本 Ubuntu 20.04 LTS + +```bash +sudo apt install -y \ + python3-flake8-blind-except \ + python3-flake8-builtins \ + python3-flake8-class-newline \ + python3-flake8-comprehensions \ + python3-flake8-deprecated \ + python3-flake8-import-order \ + python3-flake8-quotes \ + python3-pytest-repeat \ + python3-pytest-rerunfailures +``` + +## [获取 ROS 2 代码](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id6)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#get-ros-2-code "Link to this heading") + +创建工作区并克隆所有仓库: + +```bash +mkdir -p ~/ros2_humble/src +cd ~/ros2_humble +vcs import --input https://raw.githubusercontent.com/ros2/ros2/humble/ros2.repos src +``` + +## [使用 rosdep 安装依赖](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id7)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#install-dependencies-using-rosdep "Link to this heading") + +ROS 2 包是在经常更新的 Ubuntu 系统上构建的。在安装新包之前,建议您确保系统是最新的。 + +%% `sudo apt upgrade` %% + +```bash +sudo rosdep init +rosdep update +rosdep install --from-paths src --ignore-src -y --skip-keys "fastcdr rti-connext-dds-6.0.1 urdfdom_headers" +``` + +**注意**:如果您使用的是基于 Ubuntu 的发行版(如 Linux Mint)但系统未标识为 Ubuntu,您可能会收到类似 `Unsupported OS [mint]` 的错误消息。在这种情况下,请在上述命令后追加 `--os=ubuntu:jammy`。 + +## [安装额外的 DDS 实现(可选)](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id8)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#install-additional-dds-implementations-optional "Link to this heading") + +如果您想使用默认之外的 DDS 或 RTPS 供应商,可以在此处找到说明[这里](https://ros2docs.robook.org/humble/Installation/DDS-Implementations.html)。 + +## [在工作区中构建代码](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id9)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#build-the-code-in-the-workspace "Link to this heading") + +如果您已经通过其他方式(deb 包或二进制发行版)安装了 ROS 2,请确保在未激活其他安装的新环境中运行以下命令。同时确保您的 `.bashrc` 中没有 `source /opt/ros/${ROS_DISTRO}/setup.bash`。您可以使用命令 `printenv | grep -i ROS` 来确保 ROS 2 未被激活。输出应为空。 + +有关使用 ROS 工作区的更多信息,请参阅[本教程](https://ros2docs.robook.org/humble/Tutorials/Beginner-Client-Libraries/Colcon-Tutorial.html)。 + +```bash +cd ~/ros2_humble/ +colcon build --symlink-install +``` + +**注意**:如果编译所有示例时遇到问题,导致无法成功构建,您可以像使用 [CATKIN_IGNORE](https://github.com/ros-infrastructure/rep/blob/master/rep-0128.rst) 一样使用 `COLCON_IGNORE` 来忽略子树或从工作区中移除文件夹。例如:如果您想避免安装庞大的 OpenCV 库,只需在 `cam2image` 演示目录中运行 `touch COLCON_IGNORE` 即可将其排除在构建过程之外。 + +## [环境设置](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id10)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#environment-setup "Link to this heading") + +### [源化安装脚本](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id11)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#source-the-setup-script "Link to this heading") + +通过源化以下文件来设置您的环境。 + +# 如果不使用 bash,请将 ".bash" 替换为您的 shell +# 可能的取值为:setup.bash, setup.sh, setup.zsh + +```bash +. ~/ros2_humble/install/local_setup.bash +``` + +## [尝试一些示例](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#id12)[](https://ros2docs.robook.org/humble/Installation/Alternatives/Ubuntu-Development-Setup.html#try-some-examples "Link to this heading") + +在一个终端中,源化安装脚本然后运行 C++ `talker`: + +```bash +. ~/ros2_humble/install/local_setup.bash +ros2 run demo_nodes_cpp talker +``` + +在另一个终端中源化安装脚本然后运行 Python `listener`: + +```bash +. ~/ros2_humble/install/local_setup.bash +ros2 run demo_nodes_py listener +``` + +您应该能看到 `talker` 显示它正在 `Publishing` 消息,而 `listener` 显示 `I heard` 这些消息。这表明 C++ 和 Python API 都能正常工作。太好了! \ No newline at end of file diff --git a/ros/ros2/安装配置/环境配置.md b/ros/ros2/安装配置/环境配置.md new file mode 100644 index 0000000..e217f1e --- /dev/null +++ b/ros/ros2/安装配置/环境配置.md @@ -0,0 +1,8 @@ +``` bash +source install/local_setup.bash +# export ROS_DOMAIN_ID= +# echo "export ROS_DOMAIN_ID=" >> ~/.bashrc +# export ROS_LOCALHOST_ONLY=1 +# echo "export ROS_LOCALHOST_ONLY=1" >> ~/.bashrc +``` + diff --git a/ros/ros2/概念/基础概念.md b/ros/ros2/概念/基础概念.md new file mode 100644 index 0000000..f55ba1c --- /dev/null +++ b/ros/ros2/概念/基础概念.md @@ -0,0 +1,165 @@ +# ROS 2 基础概念 + +ROS 2 (Robot Operating System 2) 是一个用于构建机器人应用程序的开源框架。它提供了一套工具、库和约定,帮助开发者创建可维护、可扩展且可重用的机器人软件。 + +## 1. Node (节点) + +**节点** 是 ROS 2 中最小的可执行单元,代表一个单一功能模块。每个节点执行特定任务(如控制传感器、处理图像、规划路径等),并通过标准接口与其他节点通信。 + +- **特点**: + - 轻量级,单一职责 + - 使用命名空间避免命名冲突 + - 支持多种客户端库(C++、Python、Java等) + +- **核心概念**: + - 节点名称:唯一标识符,如 `/camera_driver` + - 命名空间:用于组织节点,如 `/robot1/camera_driver` + +## 2. Discovery (发现机制) + +**发现机制** 是 ROS 2 中节点自动发现其他节点和服务的过程。它允许节点在网络中找到彼此并建立通信,无需硬编码地址。 + +- **工作原理**: + - 使用 DDS (Data Distribution Service) 作为底层通信中间件 + - 通过参与者(Participant)、主题(Topic)和服务(Service)的发现实现 + - 自动管理连接的建立和断开 + +- **关键组件**: + - ROS 2 守护进程 `ros2 daemon`(后台运行,管理发现) + - DDS 域(Domain ID):控制节点可见性(同一域的节点才能通信) + +## 3. Interfaces (接口) + +**接口** 定义了节点之间通信的消息格式。ROS 2 提供了三种主要通信接口类型: + +### 3.1 Topics (话题) - 发布/订阅通信 + +**话题** 是节点之间传递数据的命名通道。一个节点可以**发布**(发送)数据到某个话题,其他节点可以**订阅**(接收)该话题的数据。 + +- **特点**: + - 单向、异步通信 + - 一对多或多对多通信模式 + - 消息类型严格定义(如 `std_msgs/String`、`sensor_msgs/Image`) + +- **使用场景**: + - 持续数据流(如传感器数据、状态信息) + +### 3.2 Services (服务) - 请求/响应通信 + +**服务** 实现节点之间的双向同步通信。一个节点提供**服务**,其他节点发送**请求**并等待**响应**。 + +- **特点**: + - 请求/响应模式 + - 同步通信(客户端等待服务端处理) + - 需要定义请求和响应的消息类型(.srv 文件) + +- **使用场景**: + - 一次性任务(如获取配置、执行动作) + +### 3.3 Actions (动作) - 目标导向通信 + +**动作** 是服务的扩展,支持长时间运行的任务,并提供反馈和取消功能。 + +- **特点**: + - 目标-反馈-结果模式 + - 可取消、可获取进度反馈 + - 异步执行 + - 消息类型定义在 .action 文件中 + +- **使用场景**: + - 长时间运行的任务(如导航、抓取物体) + +## 4. Parameters (参数) + +**参数** 是节点的配置值,可以在运行时动态修改。参数支持多种数据类型(整数、浮点数、字符串、布尔值等)。 + +- **管理方式**: + - 命令行设置 + - 配置文件(YAML) + - 运行时动态修改(通过 `ros2 param` 命令或 API) + +- **常用操作**: + - `ros2 param list`:列出节点参数 + - `ros2 param set`:设置参数值 + - `ros2 param get`:获取参数值 + +## 5. Introspection (内省) + +**内省** 允许开发者在运行时检查和监控 ROS 2 系统的状态。通过内省工具,您可以查看节点、话题、服务和参数的信息。 + +- **常用工具**: + - `ros2 node list`:列出所有节点 + - `ros2 topic list`:列出所有话题 + - `ros2 service list`:列出所有服务 + - `ros2 topic echo`:查看话题消息内容 + - `ros2 node info`:查看节点详细信息 + +## 6. Launch (启动系统) + +**Launch** 允许您同时启动多个节点和配置它们的参数。使用 Python 或 XML 编写的启动文件可以简化系统启动过程。 + +- **特点**: + - 同时启动多个节点 + - 配置节点参数 + - 设置命名空间和重映射 + - 支持条件启动和依赖关系 + +- **常用工具**: + - `ros2 launch`:执行启动文件 + - 启动文件格式:Python(推荐)、XML、YAML + +## 7. Client Libraries (客户端库) + +**客户端库** 是 ROS 2 提供的编程接口,允许开发者使用不同语言编写节点。 + +- **主要客户端库**: + - **rclcpp**:C++ 客户端库(推荐用于高性能应用) + - **rclpy**:Python 客户端库(推荐用于快速原型开发) + - **rcljava**:Java 客户端库 + - **其他**:Swift、Go 等语言的社区支持 + +- **核心特性**: + - 统一的 API 接口 + - 自动内存管理 + - 支持所有 ROS 2 通信模式 + +## 8. 通信中间件 + +ROS 2 使用 **DDS (Data Distribution Service)** 作为默认通信中间件,提供可靠的实时数据交换。DDS 是工业标准的中间件,适用于嵌入式系统和高性能计算。 + +- **DDS 特性**: + - 高可靠性 + - 低延迟 + - 实时支持 + - 可扩展性 + - 服务质量(QoS)配置 + +## 9. 服务质量(QoS) + +**QoS (Quality of Service)** 配置允许您控制通信的可靠性、持久性和其他特性。QoS 设置对于确保系统在不同环境下的性能至关重要。 + +- **主要 QoS 策略**: + - Reliability:可靠传输(保证交付)或最佳 effort(不保证交付) + - Durability:数据是否持久化(对晚加入的节点可见) + - History:保留消息历史的深度 + - Deadline/Lifespan:消息的截止时间和寿命 + +## 10. 系统架构概览 + +ROS 2 系统由以下层次组成: + +1. **应用层**:节点、话题、服务、动作 +2. **中间件层**:DDS 通信系统 +3. **工具层**:命令行工具、可视化工具、调试工具 +4. **硬件抽象层**:传感器、执行器、硬件接口 + +## 11. 与 ROS 1 的主要区别 + +- **通信中间件**:ROS 1 使用 TCPROS/UDPROS,ROS 2 使用 DDS +- **节点发现**:ROS 1 依赖 roscore,ROS 2 去中心化 +- **接口类型**:ROS 2 添加了 Actions +- **参数系统**:ROS 2 支持动态参数配置 +- **编译系统**:ROS 1 使用 catkin,ROS 2 使用 colcon +- **支持的语言**:ROS 2 对 Python 3 的支持更好,添加了更多语言选项 + +这些基础概念是理解和使用 ROS 2 的核心。通过掌握这些概念,您可以开始构建复杂的机器人系统,并利用 ROS 2 的强大功能。 \ No newline at end of file diff --git a/ros/履带底盘机械臂.md b/ros/履带底盘机械臂.md new file mode 100644 index 0000000..5c23b9b --- /dev/null +++ b/ros/履带底盘机械臂.md @@ -0,0 +1 @@ +[差速驱动移动基座和机械臂的规划 — MoveIt documentation documentation](https://www.ncnynl.com/ros2docs/cn/moveit2/doc/examples/mobile_base_arm/mobile_base_arm_tutorial.html) \ No newline at end of file diff --git a/大模型/DeepSeek V4 系列.md b/大模型/DeepSeek V4 系列.md new file mode 100644 index 0000000..67f2082 --- /dev/null +++ b/大模型/DeepSeek V4 系列.md @@ -0,0 +1,125 @@ +# DeepSeek V4 系列 + +> 发布日期:2026年4月24日 | 开源协议:MIT + +## 概述 + +DeepSeek V4 是深度求索(DeepSeek)在 2026 年 4 月发布的新一代大语言模型系列,包含两个版本: + +| | V4 Pro(旗舰版) | V4 Flash(轻量版) | +|---|---|---| +| **总参数量** | 1.6T(1.6万亿) | 284B(2840亿) | +| **激活参数** | ~36B/token | 13B/token | +| **上下文窗口** | 1M tokens | 1M tokens | +| **架构** | MoE(混合专家) | MoE(混合专家) | +| **定位** | 旗舰性能,对标 GPT-5 | 低成本、低延迟,接近 Pro 推理能力 | + +--- + +## 核心技术架构 + +### 1. 混合专家架构(Mixture-of-Experts, MoE) + +- V4 Pro:384 个专家/层,每次推理激活 6 个 +- V4 Flash:精简专家数量,每次推理激活 13B 参数 +- 优势:总参数大但计算量可控,推理效率高 + +### 2. 混合注意力机制(Hybrid Attention) + +- **DSA2 稀疏注意力**:降低长上下文的计算开销 +- **CSA(压缩稀疏注意力)+ HCA(重度压缩注意力)**(Flash): + - KV 缓存内存开销降低高达 90% + - 在 1M 上下文下,单 token 推理 FLOPs 仅为 V3.2 的 27% + - KV 缓存仅为 V3.2 的 10% + +### 3. 其他关键技术 + +- **流形约束超连接(mHC)**:增强残差连接,改善跨层信号传播 +- **Muon 优化器**:加速收敛,提升训练稳定性 +- **多 Token 预测(MTP)**:一次预测多个 token,加速生成 +- **DSpark 推测解码**(Flash):集成草稿模块加速推理 + +--- + +## 三种推理模式 + +| 模式 | 说明 | 适用场景 | +|---|---|---| +| **Non-think(低)** | 快速、直观的响应 | 简单对话、翻译、摘要 | +| **Think High(高)** | 显式思维链推理 | 逻辑推理、规划任务 | +| **Think Max(最大)** | 最大推理深度 | 复杂数学、竞赛编程 | + +--- + +## 关键基准测试 + +### V4 Pro 亮点 + +| 基准测试 | 得分 | 对比 | +|---|---|---| +| Codeforces Rating | 3206 | 超越 Gemini 3.1-Pro | +| LiveCodeBench | 93.5 | 与 GPT-5.4 竞争 | +| MMLU-Pro | — | 接近 GPT-5 水平 | + +### V4 Flash 亮点 + +| 基准测试 | 得分 | +|---|---| +| MMLU-Pro (EM) | 87.5 | +| GPQA Diamond | 90.1 | +| LiveCodeBench | 93.5 | +| SWE Verified (Resolved) | 80.6 | +| Terminal Bench 2.1 | 82.7 | +| BrowseComp | 83.4 | + +--- + +## 定价对比 + +### V4 Pro(通过 DeepInfra) + +| Token 类型 | 每百万 Token 价格 | +|---|---| +| 输入 | $1.74 | +| 输出 | $3.48 | +| 缓存输入 | $0.145 | + +### V4 Flash + +| Token 类型 | 每百万 Token 价格 | +|---|---| +| 输入 | ~$0.14 | +| 输出 | ~$0.28 | + +> V4 Pro 输出成本比 Claude Opus 4.7($25/1M)便宜约 7 倍 + +--- + +## 独立评测(NIST/CAISI,2026年5月) + +- V4 Pro 性能约为 **GPT-5 水平**(2025年8月发布) +- 距美国最前沿模型约 **8 个月**差距 +- CAISI 测试过的**最强中国 AI 模型** +- 在某些非公开基准(ARC-AGI-2、CTF-Archive-Diamond)上明显落后于 GPT-5.5 和 Opus 4.6 + +--- + +## 战略意义 + +1. **芯片自主**:与华为昇腾(Ascend)、寒武纪合作优化,不依赖 NVIDIA/AMD +2. **开源生态**:MIT 协议开源,模型权重在 Hugging Face 上公开 +3. **与 GPT-5.5 同日发布**:中美 AI 竞争白热化的标志性事件 +4. **自我定位坦诚**:官方公开承认距前沿 3-6 个月差距 + +--- + +## 相关链接 + +- [[Transformer 架构详解]] +- [[MoE 混合专家架构]] +- [[多模态大模型]] +- [[大模型架构基础]] + +--- + +*最后更新:2026-08-05* diff --git a/大模型/FFN 前馈网络详解.md b/大模型/FFN 前馈网络详解.md new file mode 100644 index 0000000..e19e4cb --- /dev/null +++ b/大模型/FFN 前馈网络详解.md @@ -0,0 +1,410 @@ +# FFN 前馈网络详解 + +> Feed-Forward Network — Transformer 中参数量最大(~2/3)、负责知识存储和特征变换的核心组件 + +--- + +## 一、FFN 在 Transformer 中的角色 + +``` +Transformer Block: + + 注意力层(信息混合) FFN 层(特征变换) + ┌─────────────────┐ ┌─────────────────────┐ + │ Token 之间交互 │ │ 每个 Token 独立处理 │ + │ "谁跟谁有关?" │ → │ "这个 Token 是什么意思?"│ + │ 参数量 ~1/3 │ │ 参数量 ~2/3 │ + └─────────────────┘ └─────────────────────┘ +``` + +| 组件 | 参数量占比 | 功能 | +|---|---|---| +| **注意力层** | ~1/3 | Token 间的信息路由与混合("连接信息") | +| **FFN 层** | ~2/3 | Token 内部的特征变换与知识存储("存储知识") | + +> **直觉**:注意力层决定"从哪读信息",FFN 层存储"读到的信息怎么理解"。研究表明 FFN 的权重矩阵充当了**联想记忆(Associative Memory)**——W₁ 的每一行是一个"模式检测器",W₂ 的对应列是"该模式的输出"。 + +--- + +## 二、基础公式 + +### 标准 FFN(原始 Transformer) + +``` +FFN(x) = W₂ · ReLU(W₁ · x + b₁) + b₂ +``` + +``` +输入 x(d_model 维度) + │ + ▼ +W₁: d_model → d_ff ← 升维(通常 d_ff = 4 × d_model) + │ + ▼ +激活函数(ReLU/GELU/...) ← 引入非线性 + │ + ▼ +W₂: d_ff → d_model ← 降维回原维度 + │ + ▼ +输出(d_model 维度) +``` + +### 参数量计算 + +``` +标准 FFN(无偏置): + params = d_model × d_ff + d_ff × d_model + = 2 × d_model × d_ff + = 2 × d_model × 4d_model (通常 d_ff = 4d) + = 8 × d_model² +``` + +| d_model | d_ff (4×) | FFN 参数量 | 一层总参数(含注意力) | +|---|---|---|---| +| 512 | 2048 | 2.1M | ~3M | +| 4096 (LLaMA 7B) | 11008 (约2.7×) | ~90M | ~135M | +| 8192 (LLaMA 70B) | 22016 | ~360M | ~540M | + +> 在 LLaMA 等 SwiGLU 模型中,`d_ff` 通常设为约 `8/3 × d_model`(而非 4×),以补偿 GLU 变体引入的额外参数。 + +--- + +## 三、激活函数演进路线 + +``` +2017 ─→ 2019 ────→ 2020 ──────→ 2025 +ReLU GELU SwiGLU PolyGLU / 动态路由 + │ │ │ │ + │ │ │ └─ 每个神经元学自己的激活函数 + │ │ └─ 门控线性单元,当前生产标准 + │ └─ 平滑版 ReLU,不再死神经元 + └─ 简单粗暴,负值直接清零 +``` + +### 3.1 ReLU(原始 Transformer) + +$$\text{ReLU}(x) = \max(0, x)$$ + +``` + │ + 2 ┤ ╱ + 1 ┤ ╱ + 0 ┼════●──────── ← 负半轴完全为零 + │ ╱ + -1 ┤ ╱ + └──────────── +``` + +| 优点 | 缺点 | +|---|---| +| 计算极快,硬件原生支持 | **死神经元**:一旦输出为零,梯度为零,永不恢复 | +| 稀疏激活(约 50%) | 负值信息完全丢失 | + +> **死神经元问题**:如果某个神经元的输出始终 ≤ 0(因为权重初始化或学习偏差),ReLU 的梯度永远为 0,这个神经元就"死了"——再也不会更新。 + +### 3.2 GELU(GPT-2 / BERT 时代) + +$$\text{GELU}(x) = x \cdot \Phi(x) = x \cdot \frac{1}{2}\left[1 + \text{erf}\left(\frac{x}{\sqrt{2}}\right)\right]$$ + +``` + │ + 2 ┤ ╱ + 1 ┤ ╱╱ + 0 ┼────●───────── ← 负半轴有小的非零输出 + -1 ┤╱╱ + └──────────── +``` + +| 优点 | 缺点 | +|---|---| +| 平滑可微,梯度流更好 | 计算比 ReLU 慢(erf 函数) | +| 负值有概率性"门控"而非直接清零 | 所有输入用同一个函数处理 | +| 缓解死神经元问题 | | + +> **GELU 的直觉**:把输入值 `x` 乘以它"来自正半轴的概率"——如果 x 很可能是负的,输出很小但不为零。 + +### 3.3 SiLU / Swish + +$$\text{SiLU}(x) = x \cdot \sigma(x) = \frac{x}{1 + e^{-x}}$$ + +``` + │ + 2 ┤ ╱ + 1 ┤ ╱╱ + 0 ┼─────●───────── ← 负半轴有"负沟"(non-monotonic) + -0.3┤ ╱ ╲ ← 这个沟是 SiLU 的独特特征 + └──────────── +``` + +| 关键特性 | 说明 | +|---|---| +| **自门控** | 每个值决定自己通过多少:`x · σ(x)` | +| **非单调** | 负半轴先下降再回升,能捕获复杂模式 | +| **无界正值** | 正半轴可以无限大(不像 sigmoid 有上限) | +| **平滑** | 处处可微,梯度流极好 | + +> SiLU 和 Swish 是**同一个函数**的两个名字。Google 叫它 Swish,PyTorch 叫它 SiLU。 + +--- + +## 四、GLU 门控线性单元:范式转变 + +### 4.1 从"单路激活"到"双路门控" + +``` +标准 FFN: GLU FFN: + + x x + │ ┌────┴────┐ + W₁ W_gate W_up + │ │ │ + Act σ │ + │ │ │ + W₂ └────┬────┘ + │ ⊗ (逐元素相乘) + 输出 │ + W_down + │ + 输出 +``` + +### 4.2 为什么乘法比加法强? + +> 门控 = 逐元素乘法 = 引入**二阶交互项** + +``` +GLU(x) 包含 xᵢ · xⱼ 项(不同维度之间产生交互) +FFN(x) 只有 σ(Wx) 项(每个维度独立处理) + +类比: + FFN = 每个特征独立打分 + GLU = 特征之间可以"对话"——"我是形容词,如果前面是名词就激活我" +``` + +### 4.3 SwiGLU(2020→至今的生产标准) + +$$\text{SwiGLU}(x) = \text{SiLU}(x W_{\text{gate}}) \otimes (x W_{\text{up}}) \cdot W_{\text{down}}$$ + +```python +# SwiGLU 的实际代码(也是 LLaMA、DeepSeek、Mistral 等主流模型的实现) + +class SwiGLU(nn.Module): + def __init__(self, dim, hidden_dim): + super().__init__() + # 三个权重矩阵(不是标准的两个) + self.gate_proj = nn.Linear(dim, hidden_dim, bias=False) # 门控通路 + self.up_proj = nn.Linear(dim, hidden_dim, bias=False) # 值通路 + self.down_proj = nn.Linear(hidden_dim, dim, bias=False) # 降维 + + def forward(self, x): + # gate: 门控信号(SiLU 激活) + # up: 值信号(无激活,直接通过) + return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x)) +``` + +### 4.4 参数量补偿:为什么 d_ff 变小了 + +| 方案 | 矩阵数 | 参数量 | d_ff(等参) | +|---|---|---|---| +| 标准 FFN | W₁, W₂ (2个) | 2 × d × d_ff | 4d | +| SwiGLU | W_gate, W_up, W_down (3个) | 3 × d × d_ff | **8d/3 ≈ 2.67d** | + +``` +等参数量下: + 标准 FFN:d_ff = 4d → 2 × d × 4d = 8d² + SwiGLU:d_ff = 8d/3 → 3 × d × 8d/3 = 8d² + ↑ + 参数总量相同,但 SwiGLU 表达能力更强 +``` + +> 实际中,即使参数相当,SwiGLU 的困惑度(Perplexity)也比 GELU 低约 **8.3%**(文本任务)——这是"免费的性能提升"。 + +--- + +## 五、GLU 变体对比 + +| 变体 | 门控激活函数 | 公式 | 特点 | +|---|---|---|---| +| **GLU(原始)** | Sigmoid | `σ(xW_g) ⊗ (xW_u)` | 门控有上限(0,1),表达受限 | +| **ReGLU** | ReLU | `ReLU(xW_g) ⊗ (xW_u)` | 最快,但仍可能死神经元 | +| **GeGLU** | GELU | `GELU(xW_g) ⊗ (xW_u)` | 视觉/多模态任务稍好 | +| **SwiGLU** | SiLU/Swish | `SiLU(xW_g) ⊗ (xW_u)` | **文本生成 SOTA,生产标准** | + +### 选择指南 + +| 场景 | 推荐 | 原因 | +|---|---|---| +| LLM 文本生成 | **SwiGLU** | 困惑度最低,LLaMA/DeepSeek/Mistral 全部使用 | +| 视觉编码器 | GeGLU 或 GELU | 分类任务上略优(~2% Top-1 提升) | +| 延迟敏感 | ReGLU | Relu 计算成本最低,硬件原生支持 | +| 混合模态 | 编码器 GELU + 解码器 SwiGLU | 各取所长,推理可提速 ~15% | + +--- + +## 六、FFN = 知识的"键值记忆" + +> 这个视角将 FFN 从"无聊的全连接层"升级为"模型的知识存储系统" + +### 联想记忆假说 + +``` +FFN(x) = W₂ · Act(W₁ · x) + +W₁ 的每一行 = 一个"键"(Key),检测特定模式 +W₂ 的对应列 = 一个"值"(Value),存储该模式对应的输出 + +过程: + 1. W₁·x → 将输入与所有"键"匹配(内积 = 相似度) + 2. Act → 过滤:只保留匹配度高的模式 + 3. W₂· ... → 激活的模式"写出"对应的值 +``` + +### 实验证据 + +| 发现 | 说明 | +|---|---| +| **知识定位** | FFN 的特定神经元可以对应具体的事实(如"埃菲尔铁塔在巴黎") | +| **可编辑性** | 修改 FFN 权重可以精确修改模型存储的事实(模型编辑) | +| **稀疏激活** | 对每个 Token,FFN 中只有少数神经元真正激活(和 MoE 思路一致) | +| **层间分工** | 浅层 FFN → 语法/局部模式、深层 FFN → 语义/全局知识 | + +--- + +## 七、2025 前沿:激活函数本身也"可学习" + +### 7.1 PolyGLU(2025年3月) + +> **不再固定用一种激活函数,而是让每个神经元学习自己最适合的激活函数** + +``` +PolyGLU(x) = [ Σ g_k · σ_k(x·W_gate) ] ⊗ (x·W_up) + +其中 σ_k 从候选池中选择: + { ReLU, Tanh, SiLU, GELU } + +g_k = 路由权重(每个神经元不同),训练中自动收敛 +``` + +**训练后的层间分布(19K步训练)**: + +``` +层 0-2(浅层): GELU 35-40% | Tanh 15-25% | SiLU 15-20% | ReLU ~5% +层 3-14(中层): GELU 为主,逐步过渡 +层 15-27(深层): Tanh 50-65% ← 深层网络偏好对称有界激活! +``` + +> 关键发现:深层网络的神经元**自发偏好 Tanh**(对称、有界),浅层偏好 GELU(概率性门控)。这暗示不同深度的层确实需要不同"类型"的非线性变换。 + +### 7.2 动态激活选择(LLaMA 4) + +LLaMA 4 实验在 SwiGLU 和 GELU 之间做**输入级动态切换**: +- 用轻量门控网络根据输入内容选择激活函数 +- 复杂推理任务 → 倾向于 SwiGLU(更强的特征交互) +- 简单模式匹配 → 倾向于 GELU(更快的计算) + +--- + +## 八、DeepSeek 风格的实际实现 + +### 标准 SwiGLU(如 LLaMA) + +```python +class LlamaMLP(nn.Module): + def __init__(self, config): + super().__init__() + self.gate_proj = nn.Linear(config.hidden_size, config.intermediate_size, bias=False) + self.up_proj = nn.Linear(config.hidden_size, config.intermediate_size, bias=False) + self.down_proj = nn.Linear(config.intermediate_size, config.hidden_size, bias=False) + + def forward(self, x): + return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x)) +``` + +### DeepSeek-V3 的 MoE + SwiGLU + +```python +# 每个专家就是一个 SwiGLU FFN +class DeepSeekExpert(nn.Module): + def __init__(self, dim, moe_intermediate_size): + super().__init__() + self.gate_proj = nn.Linear(dim, moe_intermediate_size, bias=False) + self.up_proj = nn.Linear(dim, moe_intermediate_size, bias=False) + self.down_proj = nn.Linear(moe_intermediate_size, dim, bias=False) + + def forward(self, x): + return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x)) + +# MoE 层:N 个专家 + 路由器 +class DeepSeekMoE(nn.Module): + def __init__(self, dim, n_routed_experts=256, n_shared_experts=2, top_k=8): + super().__init__() + self.shared_experts = nn.ModuleList([ + DeepSeekExpert(dim, dim * 2) for _ in range(n_shared_experts) + ]) + self.routed_experts = nn.ModuleList([ + DeepSeekExpert(dim, dim * 2) for _ in range(n_routed_experts) + ]) + self.gate = nn.Linear(dim, n_routed_experts, bias=False) + + def forward(self, x): + # 共享专家(始终激活) + shared_out = sum(e(x) for e in self.shared_experts) + # 路由专家(稀疏激活 Top-K) + router_logits = self.gate(x) + topk_weights, topk_ids = torch.topk(router_logits.softmax(-1), self.top_k) + routed_out = 0 + for i, expert_id in enumerate(topk_ids): + routed_out += topk_weights[i] * self.routed_experts[expert_id](x) + return shared_out + routed_out +``` + +> DeepSeek-V3 有 256 个路由专家 + 2 个共享专家,每个专家内部都是 SwiGLU FFN。详见 [[MoE 混合专家架构]]。 + +--- + +## 九、进化总览 + +``` + 标准 FFN GLU 系列 + ──────── ──────── +非线性来源: 激活函数 门控乘法 +通路数: 单路 双路(值 + 门控) +交互阶数: 一阶 二阶(xᵢ·xⱼ) +参数效率: 基准 显著更优 +参数量: 2 × d × d_ff 3 × d × d_ff +生产标准: 已过时 SwiGLU(2025年) + + 未来方向 + ──────── +激活函数选择: 可学习、每个神经元不同 +实现: PolyGLU、动态路由 +目标: 让模型自主发现最优非线性 +``` + +--- + +## 十、一句话总结 + +``` +FFN 不是"无聊的全连接层"—— +它是 Transformer 中参数最密集、负责存储世界知识的核心组件。 + +ReLU → GELU → SiLU → SwiGLU → PolyGLU 的进化线, +本质上是"从固定非线性到可学习、动态、输入感知的门控机制"的演进。 + +你正在用的 LLaMA、DeepSeek、Mistral、Qwen 的每一层中, +SwiGLU 正在用乘法门控默默地做着模型 2/3 的"思考"。 +``` + +--- + +## 相关链接 + +- [[Transformer 架构详解]] — FFN 在完整架构中的位置 +- [[大模型架构基础]] — 各组件全景概览 +- [[MoE 混合专家架构]] — FFN 的稀疏化扩展:用 N 个 SwiGLU 替代 1 个 + +--- + +*最后更新:2026-08-05* diff --git a/大模型/MoE 混合专家架构.md b/大模型/MoE 混合专家架构.md new file mode 100644 index 0000000..b547edd --- /dev/null +++ b/大模型/MoE 混合专家架构.md @@ -0,0 +1,289 @@ +# MoE 混合专家架构 + +> Mixture of Experts — 用稀疏激活实现"参数量 vs 计算量"的解耦,是 DeepSeek V4、GPT-4、Mixtral 等旗舰模型的核心架构 + +--- + +## 一、为什么要 MoE? + +### 密集模型的困境 + +传统 Transformer 中,每个 Token 流经**所有** FFN [^FFN] 参数: + +``` +Token → FFN(全部参数参与计算)→ 输出 +``` + +参数量越大 → 每次推理计算量越大 → 训练和推理成本线性增长。 + +### MoE 的核心思想 + +> **"参数多,但每次只用一小部分"** + +``` +Token → 路由器 → 选择最相关的几个专家 → 只激活它们 → 输出 + ↑ + 其他专家保持休眠 +``` + +| | 密集模型 | MoE 模型 | +|---|---|---| +| **总参数量** | 100B | 可以到 1.6T(16倍) | +| **每次推理计算量** | 100B | 仅约 36B | +| **训练效率** | 基准 | 更高(同算力下能训练更大模型) | +| **推理延迟** | 基准 | 需要加载更多权重到显存 | + +--- + +## 二、MoE 层的工作原理 + +### 数学公式 + +$$ +\text{MoE}(x) = \sum_{i \in \text{TopK}(G(x), k)} G(x)_i \cdot E_i(x) +$$ + +其中: + +| 符号 | 含义 | +|---|---| +| `G(x)` | 路由器/门控网络,输出每个专家的"置信度分数" | +| `TopK(G, k)` | 选择分数最高的 k 个专家(通常 k=2~8) | +| `E_i(x)` | 第 i 个专家(一个 FFN [^FFN] 子网络) | +| `G(x)_i` | Softmax 归一化后的专家权重 | + +### 一句话总结 + +> 输入 Token → 路由器打分 → 选 Top-K 专家 → 加权合成输出 + +### 结构图解 + +``` +输入 Token x + │ + ▼ +┌───────────┐ +│ 路由器 G │ ← 一个小型线性层,输出 N 个分数 +│ (Gate) │ (N = 专家总数) +└─────┬─────┘ + │ Softmax 归一化 + │ 选出分数最高的 k 个 + ▼ +┌─────────────────────────────────────┐ +│ N 个专家(Expert) │ +│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐│ +│ │ E₁ │ │ E₂ │ │ E₃ │... │ Eɴ ││ +│ │💤 │ │🔥 │ │💤 │ │🔥 ││ +│ └─────┘ └──┬──┘ └─────┘ └──┬──┘│ +│ │ │ │ +│ 只激活 k=2 个专家! │ │ +└─────────────┼─────────────────┼─────┘ + │ │ + └─── 加权求和 ────┘ + │ + ▼ + 输出 MoE(x) +``` + +--- + +## 三、MoE 层 vs 标准 FFN 层 + +``` +标准 Transformer 块: 使用 MoE 的 Transformer 块: + +注意力层 [^Attn] 注意力层 [^Attn] + ↓ ↓ +FFN(全部参数) 路由器 → 选择专家 + ↓ ↓ +注意力层 [^Attn] 被选中的专家(稀疏激活) + ↓ ↓ +FFN(全部参数) 注意力层 [^Attn] + ↓ + 路由器 → 选择专家 + ↓ + 被选中的专家(稀疏激活) +``` + +> **只在 FFN 层引入 MoE**,注意力层保持不变(注意力机制本身就负责 Token 间信息交互,无需稀疏化)。 + +--- + +## 四、关键设计维度 + +### 1. 专家粒度 + +| 类型 | 说明 | 示例 | +|---|---|---| +| **粗粒度** | 少量大专家(如 8 个,每个完整 FFN 大小) | 早期 MoE、Mixtral 8×7B | +| **细粒度** | 大量小专家(如 384 个微专家,每个很小) | DeepSeek-V3/V4(64 个微专家/层,激活 6 个) | + +细粒度的优势: +- 路由组合更灵活:从 N 选 k 变为 mN 选 mk,组合数暴增 +- DeepSeek V4 每层约 **3630 万种**可能的专家组合 +- 同等总参数下,每个专家更小,训练/推理更灵活 + +### 2. 共享专家 vs 路由专家 + +| 类型 | 说明 | +|---|---| +| **共享专家** | 始终激活,捕捉通用模式(语法、基础常识) | +| **路由专家** | 按 Token 动态选择,负责特定领域(数学、代码、翻译...) | + +DeepSeekMoE 采用两层设计: +- 2 个共享专家(always on) +- 62 个路由专家(每个 Token 激活 6 个) + +共享专家提升训练稳定性,但可能降低专家专门化程度。 + +### 3. 路由器设计 + +``` +简单线性路由器(当前主流): + +router_logits = W_g · x ← 一个小矩阵,N × d_model +topk_experts = TopK(softmax(router_logits), k) +``` + +实际推理时的路由模式: +- 每个 Token **独立**路由(不考虑上下文) +- 序列中相邻 Token 可能路由到不同专家 + +--- + +## 五、负载均衡 — MoE 的核心挑战 + +### 问题 + +> 如果路由器"偷懒",总是选固定的几个专家 → 其他专家闲置 → 退化为密集模型 + +### 传统方案:辅助损失(Auxiliary Loss) + +$$ +L_{total} = L_{主任务} + \alpha \cdot L_{负载均衡} +$$ + +强制惩罚专家使用不均匀的情况。**问题**:梯度冲突,可能导致训练不稳定。 + +### 2025 前沿:无梯度负载均衡 + +```python +# 动态偏置调整 — 不干扰主损失梯度 +logits_i(t+1) = W_g · x + b_i(t) - γ · (f_i(t)/f̄(t) - 1) +``` + +其中: +- `f_i(t)`:当前被路由到专家 i 的 Token 比例 +- `f̄(t)`:理想平均比例 = 1/N +- 效果:专家使用率的变异系数 < 0.1,无梯度冲突 + +--- + +## 六、2025 年前沿进展 + +### 1. DAG-MoE [^DAG](ICML 2026) + +> 不是简单加权平均专家输出,而是把选中的专家排列成**有向无环图(DAG, Directed Acyclic Graph)**,实现结构化的专家聚合(DAG 聚合) + +``` +传统 MoE: E₁↘ + E₂ → 加权平均 → 输出 + E₃↗ + +DAG-MoE: E₁ → E₃ ↘ + E₂ → E₄ → E₆ → 输出(信息流经多个专家) +``` + +- 允许**单层内多步推理** +- 模型学习最优的专家聚合结构(每个输入不同) +- 同等 FLOPs 下更强的表达能力 + +### 2. MoLE:查找表专家(ICML 2025 Oral) + +> 将训练好的 FFN 专家**重新参数化**为查找表(LUT),专家计算变为查表操作 + +- 推理速度接近密集模型 +- 大幅降低显存占用 +- 使 MoE 在内存受限设备上部署成为可能 + +### 3. MoE + MLA(Multi-head Latent Attention,多头潜在注意力) [^MLA] + +正交瓶颈联合优化: + +| 瓶颈 | 方案 | +|---|---| +| FFN 计算量大 | MoE 稀疏激活 | +| 注意力 KV 缓存大 | MLA 低秩压缩 | + +- ρ = 1/2 时:KV 缓存减少 **68%**,推理加速 **3.2×** +- 困惑度仅下降 0.8% +- DeepSeek V4 使用此组合 + +### 4. MoE-X:可解释 MoE(ICML 2025) + +- 将 MoE 层理解为等效的大型稀疏 MLP +- 强制专家内部也做稀疏激活 +- 可解释性超越 Sparse Autoencoder(SAE)方法 + +--- + +## 七、主流 MoE 模型对比 + +| 模型 | 总参数 | 激活参数 | 专家数 | 激活数 | 特点 | +|---|---|---|---|---|---| +| **Mixtral 8×7B** | 46.7B | 12.9B | 8 | 2 | 经典粗粒度 MoE | +| **DeepSeek-V3** | 671B | 37B | 256 | 8 | 细粒度 + 共享专家 | +| **DeepSeek-V4 Pro** | 1600B | 36B | 384/层 | 6 | 细粒度 + MLA + DSpark | +| **DeepSeek-V4 Flash** | 284B | 13B | 精简 | 精简 | Pro 的轻量版 | +| **GPT-4**(传闻) | 1.8T | ~280B | 16(推测) | 2 | 早批大规模 MoE | + +> 趋势:专家数量越来越多,每个专家越来越小(细粒度),激活参数占比越来越低。 + +--- + +## 八、MoE 的代价 + +| 代价 | 说明 | +|---|---| +| **显存占用** | 所有专家都在 VRAM 里,即使大部分不激活 → 需要更多 GPU | +| **通信开销** | 多 GPU 部署时,Token 需要跨 GPU 路由到专家 | +| **训练不稳定** | 负载均衡损失与主损失可能冲突 | +| **微调困难** | 稀疏激活 → 梯度更稀疏 → 微调更难收敛 | +| **批次大小** | 每个专家实际收到的 Token 少 → 需要较大 batch size | + +--- + +## 九、总结 + +``` +MoE = 用路由器在大量专家中选择少数激活,实现"参数膨胀但计算可控" + +关键取舍: + 优势:同等算力下更大的模型容量、更好的性能/成本比 + 代价:更高显存、更复杂的工程、训练和微调挑战 + +2025 年趋势: + 细粒度 → DAG 聚合 → 可解释 → 查找表推理 → 与 MLA 协同 +``` + +--- + +## 相关链接 + +- [[Transformer 架构详解]] +- [[大模型架构基础]] +- [[DeepSeek V4 系列]] + +--- + +--- + +## 脚注 + +[^FFN]: **FFN(Feed-Forward Network,前馈神经网络)**:Transformer 中每个位置的独立全连接子网络。结构为两层 MLP:`W₂ · Act(W₁ · x + b₁) + b₂`,参数量约占整个 Transformer 块的 2/3,是模型"知识存储"的主要位置。现代模型多使用 SwiGLU 激活的变体。详见 [[FFN 前馈网络详解]]。 + +[^Attn]: **注意力层(Attention Layer)**:Transformer 的核心机制,负责 Token 之间的信息交互。通过 Q(Query)、K(Key)、V(Value)三个投影矩阵,让每个 Token "看到"并加权所有其他 Token,从而捕获上下文依赖关系。多头注意力(Multi-Head Attention)并行运行多组 Q/K/V,每组关注不同的语义模式。 + +[^MLA]: **MLA(Multi-head Latent Attention,多头潜在注意力)**:DeepSeek 提出的注意力压缩技术。核心思路是将 K 和 V 首先投影到一个低维潜在空间(`d_latent << d_model`),再从中展开供注意力计算使用。这大幅减少了 KV 缓存的显存占用——在 ρ = 1/2 时可缩减 68%,且对模型质量影响极小(困惑度仅降 0.8%)。MLA 与 MoE 是正交优化:MoE 省 FFN 计算,MLA 省注意力显存,两者叠加效果倍增。 + +[^DAG]: **DAG 聚合(DAG Aggregation)**:将选中的专家按有向无环图(DAG)的结构进行串联/并联组合,而非传统的简单加权平均。每个输入路由到一组专家后,模型学习这些专家之间最优的信息流动路径——例如 E₁ 的输出作为 E₃ 的输入,E₂ 的输出则直接进入最后阶段。这允许在单层 MoE 内完成**多步推理**,表达能力强于传统加权求和,同等 FLOPs 下能取得更好性能。DAG-MoE 发表于 ICML 2026。 diff --git a/大模型/Transformer 架构详解.md b/大模型/Transformer 架构详解.md new file mode 100644 index 0000000..92dcaf0 --- /dev/null +++ b/大模型/Transformer 架构详解.md @@ -0,0 +1,425 @@ +# Transformer 架构详解 + +> 2017 年,"Attention Is All You Need" 论文用自注意力取代了 RNN/LSTM,开启了现代大语言模型时代。 + +--- + +## 一、Transformer 之前:RNN 的困境 + +``` +RNN 的处理方式(串行): +Token₁ → Token₂ → Token₃ → ... → Tokenₙ + 5ms 5ms 5ms 5ms = 5×n ms(无法并行) + +Transformer 的处理方式(并行): +Token₁ ↘ +Token₂ → 所有 Token 同时互相"看到" → 并行计算 +Token₃ ↗ ≈ 5ms(与 n 无关) +``` + +| 问题 | RNN/LSTM | Transformer | +|---|---|---| +| **并行性** | 串行,无法并行训练 | 完全并行,GPU 友好 | +| **长距离依赖** | 梯度消失/爆炸,远距离信息丢失 | 每个 Token 直接关注任意位置的 Token | +| **训练速度** | 慢(序列越长越慢) | 快得多 | +| **可解释性** | 难以解释隐藏状态 | 可直接可视化注意力权重 | + +--- + +## 二、整体架构:编码器-解码器 + +原始 Transformer 用于机器翻译,包含编码器和解码器两部分。 + +``` + ┌─────────────────────────────────┐ + │ 编码器(Encoder) │ + │ ┌───────────────────────────┐ │ +"我 爱 北京" → │ │ Encoder Block × 6 │ │ + │ │ Self-Attn + FFN │ │ + │ └───────────────────────────┘ │ + └──────────────┬──────────────────┘ + │ 编码后的表示(K, V) + ▼ + ┌─────────────────────────────────┐ + │ 解码器(Decoder) │ + │ ┌───────────────────────────┐ │ + │ │ Decoder Block × 6 │ │ + │ │ ① Masked Self-Attn │ │ → "I love Beijing" + │ │ ② Cross-Attn (用 K,V) │ │ + │ │ ③ FFN │ │ + │ └───────────────────────────┘ │ + └─────────────────────────────────┘ +``` + +### 一个 Block 内部(原始设计) + +``` +输入 x + │ + ├──→ Multi-Head Self-Attention ──→ ⊕ ──→ LayerNorm ──→ + │ ↑ ↑ + │ 残差连接 x 输出 + │ + └──→ Feed-Forward Network ──→ ⊕ ──→ LayerNorm ──→ 输出 + ↑ ↑ + 残差连接 传给下一层 +``` + +### 两种主流归一化位置 + +| 方式 | 归一化位置 | 代表模型 | 特点 | +|---|---|---|---| +| **Post-LN** | 残差之后 | 原始 Transformer | 训练不稳定,需要 warmup | +| **Pre-LN** | 子层之前 | GPT 系列、LLaMA | 训练更稳定,无需大量 warmup | + +``` +Post-LN:x + Attn(LayerNorm(x)) ← 原始论文 +Pre-LN: x + Attn(LayerNorm(x)) 错 — 实际上是: +Pre-LN:LayerNorm(x + Attn(x)) 错 — Pre-LN 是: + +Pre-LN 实际:x + Attn(LayerNorm(x)) — 等等,让我用图表示清楚: + +Post-LN: x → SubLayer → Norm → + → 输出 +Pre-LN: x → Norm → SubLayer → + → 输出 +``` + +> Pre-LN 先将输入归一化再送入子层,然后做残差。GPT/LLaMA 全系使用 Pre-LN(或 RMSNorm + Pre-LN 变体)。 + +--- + +## 三、自注意力机制:完整推演 + +### 3.1 从"查字典"理解 Q/K/V + +| 投影 | 类比 | 数学 | 含义 | +|---|---|---|---| +| **Q(Query)** | 你的搜索关键词 | `X · W_Q` | "我在找什么信息?" | +| **K(Key)** | 所有条目的索引 | `X · W_K` | "每个词身上有什么标签?" | +| **V(Value)** | 条目的实际内容 | `X · W_V` | "每个词的实际信息是什么?" | + +### 3.2 逐步计算示例 + +假设输入句子 "我 爱 NLP",模型维度 d=4,头维度 d_k=2: + +**Step 1 — 输入嵌入** +``` +我: [0.1, 0.3, 0.5, 0.2] +爱: [0.4, 0.1, 0.3, 0.6] +NLP: [0.2, 0.5, 0.1, 0.3] +``` + +**Step 2 — 计算 K 和 Q(只演示一个头的投影)** +``` +K = X · W_K (3×4)×(4×2) = 3×2 矩阵 +K_我 = [0.8, 0.2] +K_爱 = [0.3, 0.9] +K_NLP = [0.5, 0.4] + +Q_爱 = [0.6, 0.3] ("爱"这个位置的 Query) +``` + +**Step 3 — 计算注意力分数(Q_爱 × K^T)** +``` +Q_爱 · K_我 = 0.6×0.8 + 0.3×0.2 = 0.48 + 0.06 = 0.54 +Q_爱 · K_爱 = 0.6×0.3 + 0.3×0.9 = 0.18 + 0.27 = 0.45 +Q_爱 · K_NLP = 0.6×0.5 + 0.3×0.4 = 0.30 + 0.12 = 0.42 + +scores = [0.54, 0.45, 0.42] +``` + +**Step 4 — 缩放 + Softmax** +``` +scaled = scores / √2 = [0.38, 0.32, 0.30] +weights = softmax(scaled) = [0.35, 0.33, 0.32] +``` + +**Step 5 — 加权求和 V** +``` +V_我 = [0.7, 0.1] +V_爱 = [0.2, 0.8] +V_NLP = [0.4, 0.5] + +output_爱 = 0.35×[0.7,0.1] + 0.33×[0.2,0.8] + 0.32×[0.4,0.5] + = [0.245, 0.035] + [0.066, 0.264] + [0.128, 0.160] + = [0.439, 0.459] +``` + +> 位置"爱"的输出融合了"我"(35%)、"NLP"(32%)和自身(33%)的信息——这正是"理解上下文"的本质。 + +### 3.3 矩阵形式(实际实现) + +$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) V$$ + +- **QK^T**:N×N 的注意力矩阵,每对 Token 一个分数 +- **÷ √d_k**:缩放因子。d_k 越大点积值越大 → softmax 趋向 one-hot → 梯度消失。除以 √d_k 保持方差 ≈ 1 +- **Softmax**:沿最后维(Key 维度)归一化,每行和为 1 +- **× V**:用注意力权重对 Value 加权求和 + +--- + +## 四、多头注意力:并行多个"视角" + +### 4.1 为什么需要多头? + +``` +单头可能只学到一种注意力模式: + "我" → 关注了 "爱" + "爱" → 关注了 "北京" + 所有头都只关注相邻词 ← 浪费了注意力的表达能力 + +多头允许并行学习多种模式: + 头 1:语法结构(主语→谓语) + 头 2:长距离共指("它"→ 前文的"北京") + 头 3:语义关联("医生"→ "医院"→ "病人") + 头 4:位置模式(局部上下文窗口) +``` + +### 4.2 数学公式 + +$$\text{head}_i = \text{Attention}(Q W_i^Q, K W_i^K, V W_i^V)$$ + +$$\text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, ..., \text{head}_h) W^O$$ + +每个头有自己独立的投影矩阵 W_Q、W_K、W_V,维度为 d_model × d_k(其中 d_k = d_model / h)。 + +### 4.3 计算量并不是 h 倍! + +| | 单头 (d_model=512) | 8头 (每头 d_k=64) | +|---|---|---| +| Q投影参数 | 512×512 = 262K | 8×512×64 = 262K | +| K投影参数 | 同上 | 同上 | +| V投影参数 | 同上 | 同上 | +| 总参数 | ≈ 786K | ≈ 786K + W_O(512×512) ≈ 1M | + +> 计算量大致相同,只是**把工作分给多个头并行做**,每个头在更小的空间(d_k)中关注不同的模式。 + +### 4.4 生产实践中的头数配置 + +| 模型 | d_model | 头数 | d_k | +|---|---|---|---| +| 原始 Transformer | 512 | 8 | 64 | +| GPT-3 | 12288 | 96 | 128 | +| LLaMA 70B | 8192 | 64 | 128 | +| DeepSeek-V3 | — | — | 使用 MLA 替代标准多头 | + +--- + +## 五、位置编码:告诉模型"顺序" + +注意力机制本身是**置换不变**的——打乱输入顺序,注意力分数矩阵只是行列交换,输出值不变。所以必须显式注入位置信息。 + +### 方案对比 + +| 方案 | 原理 | 优点 | 缺点 | 代表模型 | +|---|---|---|---|---| +| **Sinusoidal(正弦)** | 不同频率的正弦/余弦波叠加 | 可外推、无参 | 固定模式 | 原始 Transformer | +| **Learned** | 可学习的 pos_embed 表 | 灵活 | 不能超出训练长度 | BERT、ViT | +| **RoPE(旋转位置编码)** | 用旋转矩阵编码相对位置 | 天然编码相对位置、可外推 | 长序列扩展需技巧 | LLaMA、Qwen、DeepSeek | +| **ALiBi** | 给注意力分数加线性偏置 | 简单、外推最强 | 表达能力有限 | BLOOM | + +### RoPE 核心思想 + +> **不是往 embedding 里加位置向量,而是把 Q 和 K "旋转"一个角度,角度大小取决于位置。** + +``` +位置 m 的 Q:旋转 m×θ +位置 n 的 K:旋转 n×θ + +Q·K = (rotated_Q_m)·(rotated_K_n) = 关于 (m-n) 的函数 + ↑ + 只依赖相对位置! +``` + +RoPE 扩展: +- **NTK-aware scaling**:调高基频(如 10000→500000),让旋转更慢,支持更长上下文 +- **YaRN**:NTK + 额外微调,将 Llama 从 4K 扩展到 128K + +--- + +## 六、三种架构变体:选哪种? + +### 6.1 编码器-only(如 BERT) + +``` +输入:"我 [MASK] 北京" → 编码器 → 每个位置的上下文表示 → 预测 [MASK] = "爱" + +特点: + - 双向注意力(能看到整个句子) + - 适合:分类、实体识别、语义搜索 + - 不能做生成(没有解码器) +``` + +### 6.2 解码器-only(如 GPT、LLaMA、DeepSeek V4) + +``` +输入:"今天天气" → 因果注意力(只看左边)→ 预测下一个 Token "真" + "今天天气真" → ... → 预测 "好" + +特点: + - 因果掩码(Causal Mask):每个 Token 只能看自己和左边 + - 适合:对话、代码生成、创意写作 + - 自回归生成,输入=输出(训练时位移一位即可) + - 现代 LLM 几乎全部使用此方案 +``` + +**因果掩码示意**: + +``` +注意力分数矩阵(× = 被 mask 为 -∞): + + 我 爱 北京 天安门 +我 ✓ × × × ← "我"只能看到自己 +爱 ✓ ✓ × × ← "爱"能看到"我"和自己 +北京 ✓ ✓ ✓ × ← ... +天安门✓ ✓ ✓ ✓ +``` + +### 6.3 编码器-解码器(如 T5) + +``` +编码器(双向):处理源语言 → 生成 K、V +解码器(因果 + 交叉注意力):用 K、V 辅助生成目标语言 + +交叉注意力(Cross-Attention): + 解码器的 Q ← 来自解码器自身("这句话接下来该说什么?") + 解码器的 K,V ← 来自编码器("原文说了什么?") +``` + +| 架构 | 自注意力方式 | 能否生成 | 代表 | 适合任务 | +|---|---|---|---|---| +| 编码器-only | 双向 | ❌ | BERT | 理解/分类 | +| 解码器-only | 因果(单向) | ✅ | GPT, LLaMA | 生成/对话 | +| 编码器-解码器 | 双向 + 交叉 | ✅ | T5, BART | 翻译/摘要 | + +--- + +## 七、训练与推理 + +### 7.1 训练:Teacher Forcing + +``` +输入: "今天 天气 真" 目标: "天气 真 好" + ↑ + 模型被训练来预测每个位置的下一个 Token + +实际一次性计算: + 输入 [今天, 天气, 真] + → 因果掩码确保"今天"看不到后面 + → 输出 [P(天气), P(真), P(好)] + → Loss = CrossEntropy(预测, 实际目标) +``` + +> 训练时**一次前向**算出所有位置的预测,因为目标已知、且有因果掩码保护。 + +### 7.2 推理:自回归生成 + +``` +训练时可以并行(目标已知),推理必须串行(目标未知): + +Step 1: "今天" → 预测 "天气" +Step 2: "今天天气" → 预测 "真" +Step 3: "今天天气真" → 预测 "好" +Step 4: "今天天气真好" → 预测 + +每次都要重新计算全序列?→ 不,用 KV Cache! +``` + +### 7.3 KV Cache:推理加速的关键 + +``` +未使用 KV Cache: + Step 1:计算 "今天" 的 Q、K、V ──────────── 1个Token + Step 2:计算 "今天天气" 的 Q、K、V ──────── 2个Token ← 重新算了"今天"! + Step 3:计算 "今天天气真" 的 Q、K、V ────── 3个Token ← 又重算了! + ... + +使用 KV Cache: + Step 1:计算 "今天" → 缓存 K₁、V₁ + Step 2:只算 "天气" 的 Q、K、V + 用缓存的 K₁、V₁ → 缓存 K₁K₂、V₁V₂ + Step 3:只算 "真" 的 Q、K、V + 用缓存的 K₁K₂、V₁V₂ → ... + ... + 每个 Step 只算 1 个新 Token!开销从 O(n²) 降到 O(n)(单步)。 +``` + +> KV Cache 的代价:显存占用随序列长度线性增长。MLA(多头潜在注意力)通过低秩压缩解决此问题——详见 [[MoE 混合专家架构#MLA(Multi-head Latent Attention,多头潜在注意力)|MLA 详解]]。 + +--- + +## 八、高效注意力变体 + +标准自注意力是 **O(n²)** 复杂度(n = 序列长度)。对长序列需优化: + +### 8.1 FlashAttention(事实标准) + +> **IO 感知的精确注意力算法**——数学结果完全等价于标准注意力,但通过算子融合大幅减少显存读写。 + +``` +标准计算: FlashAttention: + QK^T → 写回 HBM 将 Q、K、V 分块(tile) + Softmax → 写回 HBM 每个块在 SRAM 中完成全部计算 + 乘 V → 写回 HBM 只有最终结果写回 HBM + ↑ 3次 HBM 读写 ↑ 约 1/n 的 HBM 读写 +``` + +实测效果:相比朴素实现,吞吐量提升 **~32%**(A100),现为 PyTorch 2.0+ 默认后端。 + +### 8.2 稀疏/线性注意力(长序列场景) + +| 方案 | 策略 | 复杂度 | 代表 | +|---|---|---|---| +| **Longformer** | 局部滑动窗口 + 全局 Token | O(n) | 文档级 NLP | +| **BigBird** | 局部 + 全局 + 随机 | O(n) | — | +| **Performer** | 随机特征近似 softmax | O(n) | — | +| **Mamba/SSM** | 状态空间模型替代注意力 | O(n) | 超长序列 | + +> 经验法则:序列 < 4K Token → 标准注意力 + FlashAttention 即可。长文档/代码库场景才需稀疏注意力或 SSM。 + +--- + +## 九、现代生产优化总览 + +| 优化手段 | 效果 | 代价 | +|---|---|---| +| **混合精度(bf16/fp16)** | 训练/推理速度翻倍 | 质量损失可忽略 | +| **梯度检查点** | 显存降低 50%+ | 训练慢 20% | +| **FlashAttention** | 推理加速 ~30%,显存降低 | 无(数学等价) | +| **算子融合(RMSNorm, xFormers)** | 减少 kernel launch 开销 | 无 | +| **序列分桶** | 减少 padding 浪费 | 实现复杂度增加 | +| **量化(INT8/INT4)** | 显存降低 4-8× | 轻微质量下降 | + +--- + +## 十、总结 + +``` +Transformer 的核心思想就三条: + +1. 自注意力(Self-Attention) + Q·K 算关联 → Softmax 归一化 → ×V 合成上下文 + 每个 Token 直接"看到"所有 Token + +2. 多头(Multi-Head) + 并行跑多个注意力,每个头学不同的关系模式 + 总计算量不变,表达能力翻倍 + +3. 位置编码(Positional Encoding) + 注意力不感知顺序 → 注入位置信息 + RoPE 是当前主流:Q/K 旋转角度 = 位置函数 + +Transformer 不只是一篇论文—— +它是整个现代大语言模型时代的起点。 +``` + +--- + +## 相关链接 + +- [[大模型架构基础]] — 大模型的各组件总览 +- [[FFN 前馈网络详解]] — Transformer 中参数量最大的组件 +- [[MoE 混合专家架构]] — 如何用稀疏专家替代 FFN +- [[多模态大模型]] — Transformer 如何扩展到图像/音频 +- [[DeepSeek V4 系列]] — Transformer + MoE + MLA 的实际应用 + +--- + +*最后更新:2026-08-05* diff --git a/大模型/多模态大模型.md b/大模型/多模态大模型.md new file mode 100644 index 0000000..aefd10c --- /dev/null +++ b/大模型/多模态大模型.md @@ -0,0 +1,140 @@ +# 多模态大模型(Multimodal LLM, MLLM) + +## 什么是多模态? + +**模态(Modality)** = 数据的感知/表达形式。人类通过多种模态理解世界: + +| 模态 | 示例 | +|---|---| +| **文本** | 文章、代码、对话 | +| **图像** | 照片、图表、截图 | +| **音频** | 语音、音乐、环境声 | +| **视频** | 连续图像帧 + 音频 | + +**多模态大模型** = 能同时理解和处理**多种模态数据**的 AI 模型,而非仅限于文本。 + +--- + +## 为什么需要多模态? + +> 纯文本模型只能"读文字",无法"看图片"、"听声音"。 + +现实世界的信息天然是多模态的: +- 医生既要看病历(文本),也要看 CT 片(图像) +- 自动驾驶需要同时处理摄像头(图像)、雷达(点云)、地图(结构化数据) +- 社交媒体帖子包含文字 + 图片 + 视频 + +--- + +## 基本架构(三大组件) + +``` +┌─────────────────────┐ +│ 视觉编码器 │ ← 处理图像/视频输入 +│ Vision Encoder │ (如 ViT、SigLIP) +└────────┬────────────┘ + │ 视觉特征 + ▼ +┌─────────────────────┐ +│ 投影器/连接器 │ ← 将视觉特征映射到语言空间 +│ Projector │ (如 MLP、Q-Former) +└────────┬────────────┘ + │ 对齐后的 token + ▼ +┌─────────────────────┐ +│ 大语言模型 │ ← 核心推理引擎 +│ LLM Backbone │ (如 DeepSeek、LLaMA、Qwen) +└─────────────────────┘ +``` + +### 工作流程 + +1. 图像 → 视觉编码器 → 视觉特征向量 +2. 视觉特征 → 投影器 → 对齐到语言模型的 token 空间 +3. 文本 token + 视觉 token → LLM → 生成回复 + +--- + +## 核心能力 + +| 能力 | 说明 | 示例 | +|---|---|---| +| **视觉问答(VQA)** | 根据图片回答问题 | "这张图里有几只猫?" | +| **图像描述** | 自动生成图片文字描述 | 为盲人描述照片内容 | +| **多模态对话** | 图文混合交互 | "分析这张财报图表" | +| **OCR 理解** | 理解图片中的文字 | 识别截图、海报、PDF | +| **视觉推理** | 多步骤逻辑推理 | "如果把这个方块旋转90°会怎样?" | + +--- + +## 主流多模态模型(2025-2026) + +| 模型 | 开发商 | 特点 | +|---|---|---| +| **GPT-4V / GPT-4o** | OpenAI | 原生多模态,实时语音+视觉 | +| **Gemini 系列** | Google | 原生多模态,Ultra/Pro/Flash/Nano 全系覆盖 | +| **Claude 系列** | Anthropic | 强大的图像理解、图表分析能力 | +| **Qwen-VL 系列** | 阿里通义 | 开源,中英双语 | +| **InternVL 系列** | 上海 AI 实验室 | 开源,CVPR 2025 发表 Mono-InternVL | +| **DeepSeek-VL** | DeepSeek | 注意:V4 系列目前 **仅文本**,视觉版待发布 | +| **LLaVA 系列** | 学术界 | 开源先驱,推动 MLLM 研究方向 | + +--- + +## 2025 年前沿方向 + +### 1. 高效/轻量化 MLLM +- 视觉 Token 压缩(降低 Transformer 二次复杂度) +- MoE 架构(如 MoE-LLaVA) +- 边缘设备部署(MobileVLM、TinyLLaVA、Gemini Nano) + +### 2. 单体式 MLLM(Monolithic MLLM) +- **Mono-InternVL**(CVPR 2025):将视觉编码直接集成到 LLM 内部 +- 减少 67% 首 Token 延迟,解决灾难性遗忘 + +### 3. 长链视觉推理 +- **Insight-V**:多智能体系统(推理 agent + 总结 agent) +- 跨 7 个基准平均提升 7.5% + +### 4. 统一多模态表征 +- **UnifiedMLLM**:单一模型处理多种多模态任务 + +--- + +## 主要挑战 + +1. **长序列效率**:一张图 = 数百到数千个 token,多图/视频成本极高 +2. **幻觉问题**:模型可能"看到"不存在的物体 +3. **计算成本**:训练和推理资源消耗远超纯文本模型 +4. **评估困难**:多模态基准测试尚不成熟 +5. **安全对齐**:视觉输入可能绕过文本安全过滤器 + +--- + +## 与纯文本模型对比 + +| 维度 | 纯文本 LLM | 多模态 MLLM | +|---|---|---| +| 输入 | 仅文本 | 文本 + 图像 + 音频 + 视频 | +| 参数量 | 较小(相对) | 需额外的视觉编码器参数 | +| 推理成本 | 较低 | 较高(视觉 token 开销大) | +| 应用范围 | 对话、写作、编程 | 医疗影像、自动驾驶、设计 | +| 成熟度 | 较高 | 快速发展中 | + +--- + +## 总结 + +多模态是 AI 走向通用人工智能(AGI)的关键一步。当前的 V4 Pro/Flash 等纯文本模型虽强,但"看不到世界"仍是巨大局限。理解多模态架构和原理,是理解下一代 AI 的必要基础。 + +--- + +## 相关链接 + +- [[Transformer 架构详解]] +- [[DeepSeek V4 系列]] +- [[大模型架构基础]] + +--- + +*最后更新:2026-08-05* diff --git a/大模型/大模型架构基础.md b/大模型/大模型架构基础.md new file mode 100644 index 0000000..4611b3d --- /dev/null +++ b/大模型/大模型架构基础.md @@ -0,0 +1,248 @@ +# 大模型架构基础 + +> 理解现代大语言模型的底层架构 — Transformer、注意力机制与关键组件 + +--- + +## 发展脉络 + +``` +2017 Transformer 论文 + │ "Attention Is All You Need" + ▼ +2018 GPT-1 / BERT + │ 解码器-only / 编码器-only + ▼ +2020 GPT-3(175B)— Scaling Law 确立 + ▼ +2022 ChatGPT / GPT-3.5 — RLHF 对齐 + ▼ +2023 GPT-4 / LLaMA / Claude 2 + │ 多模态、MoE 兴起 + ▼ +2024 LLaMA 3 / Qwen 2.5 / DeepSeek-V3 + ▼ +2025 GPT-5 / Claude Opus 5 / DeepSeek-V4 + 大规模 MoE、混合注意力、推理时扩展 +``` + +--- + +## 一、Transformer 架构 + +现代大语言模型的基石,发表于 2017 年。核心思想:用**自注意力机制**取代循环/卷积,实现并行计算。深度讲解见 [[Transformer 架构详解]]。 + +### 架构总览 + +``` + ┌──────────────┐ +输入文本 → │ Embedding │ → Token 向量 + └──────┬───────┘ + ▼ + ┌─────────────────────────────┐ + │ Transformer Block × N │ ← 重复 N 层(数十到数百层) + │ ┌───────────────────────┐ │ + │ │ Multi-Head Attention │ │ ← 核心:自注意力 + │ │ + Layer Norm + 残差 │ │ + │ ├───────────────────────┤ │ + │ │ Feed-Forward (FFN) │ │ ← 逐位置的全连接网络 + │ │ + Layer Norm + 残差 │ │ + │ └───────────────────────┘ │ + └─────────────┬───────────────┘ + ▼ + ┌──────────────┐ + │ 输出头 │ → 预测下一个 Token + └──────────────┘ +``` + +### 三种变体 + +| 类型 | 代表模型 | 特点 | +|---|---|---| +| **编码器-only** | BERT、RoBERTa | 双向注意力,适合理解任务(分类、NER) | +| **解码器-only** | GPT 系列、LLaMA、DeepSeek | 因果注意力(只看左边),适合生成任务 | +| **编码器-解码器** | T5、BART | 融合两者,适合翻译、摘要 | + +> 现代大语言模型**几乎全部使用解码器-only**(自回归生成)。 + +--- + +## 二、自注意力机制(Self-Attention) + +### 直观理解 + +> 让每个词"看到"句子中所有其他词,并决定应该关注哪些。 + +``` +"我 爱 北京 天安门" + │ │ │ │ + └─────┼──────┼───────┘ + │ │ + 每个词都和所有词计算关联度(注意力权重) +``` + +### 数学过程 + +对每个输入的 Token 向量,计算三个投影: + +| | 符号 | 含义 | +|---|---|---| +| **Q(Query)** | 查询 | "我在找什么?" | +| **K(Key)** | 键 | "我有什么?" | +| **V(Value)** | 值 | "我的实际内容" | + +$$ +\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) V +$$ + +步骤: +1. **Q × K^T** → 计算每对 token 之间的关联分数(注意力矩阵) +2. **÷ √d_k** → 缩放,防止梯度消失 +3. **Softmax** → 归一化为概率分布 +4. **× V** → 用注意力权重加权求和,得到输出 + +### 多头注意力(Multi-Head Attention) + +> 不是做一次注意力,而是并行做多次(如 8/16/32 个头),每个头关注不同的语义模式。 + +- 头 1 可能关注"语法结构" +- 头 2 可能关注"实体关系" +- 头 3 可能关注"长距离依赖" + +--- + +## 三、关键组件 + +### 1. Token 与 Tokenizer + +| 概念 | 说明 | +|---|---| +| **Token** | 文本被拆分的最小语义单元 | +| **Tokenizer** | 将文本切分为 Token 的工具(BPE、SentencePiece 等) | +| **词表大小** | 通常 32K ~ 256K,DeepSeek V4 使用了更大词表 | + +``` +"Hello, world!" → ["Hello", ",", " world", "!"] +"你好世界" → ["你好", "世界"] +``` + +### 2. 位置编码(Positional Encoding) + +Transformer 本身**不感知顺序**,需要额外注入位置信息: + +| 类型 | 说明 | 代表 | +|---|---|---| +| **绝对位置编码** | 每个位置有唯一的向量 | 原始 Transformer 的正弦编码 | +| **相对位置编码** | 编码 token 之间的相对距离 | T5 的相对偏置 | +| **旋转位置编码(RoPE)** | 对 Q/K 做旋转,编码相对位置 | LLaMA、DeepSeek、Qwen 主流方案 | + +### 3. 前馈网络(Feed-Forward Network, FFN) + +``` +FFN(x) = Act(W₂ · Act(W₁ · x + b₁) + b₂) +``` + +- 两层全连接,中间有激活函数(GELU/SwiGLU) +- 参数量占比最大(约 2/3) +- SwiGLU 是现代模型的首选激活函数 +- 深度讲解见 [[FFN 前馈网络详解]] + +### 4. 残差连接(Residual Connection) + +``` +输出 = LayerNorm(x + SubLayer(x)) +``` + +- 缓解深层网络的梯度消失 +- 让模型可以"跳过"不必要的变化 +- GPT 使用 Pre-LN(层归一化在子层之前) + +### 5. 层归一化(Layer Normalization) + +- 对每个样本的特征维度做归一化 +- 稳定训练、加速收敛 +- 现代主流:**RMSNorm**(去掉均值中心化,更快更简单) + +--- + +## 四、训练范式 + +``` +┌──────────────┐ +│ 1. 预训练 │ 海量互联网文本,无监督学习(预测下一个 Token) +│ Pretraining │ 数十 TB 数据,数万 GPU,数周到数月 +└──────┬───────┘ + ▼ +┌──────────────┐ +│ 2. 监督微调 │ 高质量人工标注的指令-回复对 +│ SFT │ 让模型学会"对话格式"和"遵循指令" +└──────┬───────┘ + ▼ +┌──────────────┐ +│ 3. 对齐训练 │ RLHF / DPO / RLVR +│ Alignment │ 让模型输出更安全、更有用、更符合人类偏好 +└──────────────┘ +``` + +### 关键概念 + +| 概念 | 说明 | +|---|---| +| **Scaling Law** | 模型性能随参数量、数据量、计算量幂律增长 | +| **涌现能力** | 大模型独有的、小模型没有的能力(如思维链推理) | +| **RLHF** | 基于人类反馈的强化学习 — 训练奖励模型指导策略优化 | +| **DPO** | 直接偏好优化 — 更简单地对齐方法,不需要单独的奖励模型 | + +--- + +## 五、推理时技术 + +### 自回归生成(Autoregressive Generation) + +``` +输入:"今天天气" → 预测下一个 Token "真" + "今天天气真" → 预测下一个 Token "好" + "今天天气真好" → 预测下一个 Token ""(停止) +``` + +每次生成一个 Token,直到输出结束符或达到最大长度。 + +### 关键概念 + +| 概念 | 说明 | +|---|---| +| **Temperature** | 控制随机性,越高越随机(创造性高),越低越确定 | +| **Top-p(核采样)** | 只从累积概率 ≥ p 的最少 Token 集合中采样 | +| **Top-k** | 只从概率最高的 k 个 Token 中采样 | +| **KV Cache** | 缓存已生成 Token 的 Key/Value,避免重复计算,加速推理 | +| **上下文窗口** | 模型能同时"看到"的最大 Token 数(现在主流 128K~1M) | + +--- + +## 六、当前主流架构扩展 + +### MoE(混合专家) + +> 详见 [[MoE 混合专家架构]] + +- 不是所有参数都参与每次推理 +- 每个 Token 只路由到少数"专家"子网络 +- 总参数极大但计算量可控 + +### 多模态扩展 + +> 见 [[多模态大模型]] + +- 在 LLM 基础上添加视觉/音频编码器 +- 通过投影器对齐不同模态的 Token + +--- + +## 扩展阅读 + +- 原始论文:[Attention Is All You Need (2017)](https://arxiv.org/abs/1706.03762) +- [The Illustrated Transformer](https://jalammar.github.io/illustrated-transformer/) — 图文详解 Transformer + +--- + +*最后更新:2026-08-05* diff --git a/工作/Pasted image 20260402112914.png b/工作/Pasted image 20260402112914.png new file mode 100644 index 0000000..de728f4 Binary files /dev/null and b/工作/Pasted image 20260402112914.png differ diff --git a/工作/Pasted image 20260402112951.png b/工作/Pasted image 20260402112951.png new file mode 100644 index 0000000..a3b9eb8 Binary files /dev/null and b/工作/Pasted image 20260402112951.png differ diff --git a/工作/VCU控制逻辑_精简版.md b/工作/VCU控制逻辑_精简版.md new file mode 100644 index 0000000..9168b10 --- /dev/null +++ b/工作/VCU控制逻辑_精简版.md @@ -0,0 +1,67 @@ +# VCU控制逻辑(精简版) + +## 一、核心定位 +VCU是车辆核心控制单元,设计原则:**功能简单、运行稳定**,是整车控制的基石,负责协调各子系统工作。 + +## 二、对接子系统 +VCU通过CAN总线与以下部件通信: +- BMS(电池管理系统)、OBC(车载充电机) +- 电机控制器、灯光控制系统 +- ORIN(上层自动驾驶平台)、遥控器、机械臂控制器 + +--- + +## 三、核心控制逻辑 +### 1. 充电控制 +- 检测到OBC可充电后,优先等待ORIN指令,**5分钟超时自动充电** +- 电量充满后自动发送停止充电指令 +- 长时间停在充电区且无上层控制时,**电量低于25%自动充电**,充满自停 + +### 2. 驾驶模式控制 +| 状态 | 控制逻辑 | +|------|----------| +| 遥控器未开机 | 等待ORIN连接使能,进入自动驾驶模式 | +| 遥控器开机-手动模式 | 完全不响应ORIN指令,所有控制以遥控器为准 | +| 遥控器开机-自动模式 | ORIN可以接管车辆控制 | + +### 3. 机械臂控制 +- 通过遥控器E拨杆切换底盘/机械臂模式,**两种模式互斥** +- 机械臂手动模式:不响应ORIN机械臂指令,完全由遥控器控制 +- 遥控器操作完全兼容《履带车T10遥控器协议》,支持5个关节+滚刷控制 + +### 4. 高优先级刹车(最高优先级) +- 独立刹车摇杆,**全模式生效**,不受手自动模式限制 +- 拉动幅度对应刹车力度,线性控制减速度,最大不超过系统限值,避免急停 +- 刹车期间临时上报ORIN为手动模式,屏蔽上层速度指令,释放后自动恢复原模式 + +### 5. 电机控制 +- 支持单摇杆原地转向 +- 最大加速度/减速度可配置,避免急停 +- 遥控器速度突降时平滑减速,不直接切断动力 + +### 6. 灯光控制 +- 自动驾驶指示灯:自动驾驶模式点亮,手动模式熄灭 +- 转向灯:转向指令触发,回正自动关闭 +- 刹车灯:减速或驻车时点亮 +- 远近光灯:接收上层/遥控器指令控制 + +--- + +## 四、控制优先级(从高到低) +1. **高优先级刹车摇杆** > 2. 遥控器手动模式 > 3. ORIN自动驾驶 + +--- + +## 五、关键配置参数 +| 参数 | 默认值 | 说明 | +|------|--------|------| +| 充电等待超时 | 5分钟 | 检测到可充电后等待上层指令的最长时间 | +| 自动充电SOC阈值 | 25% | 低于该值自动启动充电 | +| 最大加速度 | 1m/s² | 正向加速度上限 | +| 最大减速度 | 1m/s² | 减速上限(刹车力度不超过该值) | +| CAN通信超时 | 500ms | 连续未收到报文判定为通信丢失 | + +--- + +## 六、核心安全机制 +1. 通信丢失保护:对应模式下减速停车,上报故障 diff --git a/工作/VCU控制逻辑(v0.2).md b/工作/VCU控制逻辑(v0.2).md new file mode 100644 index 0000000..80c57cf --- /dev/null +++ b/工作/VCU控制逻辑(v0.2).md @@ -0,0 +1,234 @@ +# VCU(车辆控制单元)控制逻辑文档 + +## 1. 概述 +VCU(Vehicle Control Unit)是车辆的核心控制中心,作为整车控制的基石,设计原则为**功能简单、运行稳定**,负责协调车辆各子系统的工作。 + +### 1.1 系统架构 +VCU通过CAN总线与以下子系统直接通信: +- **BMS(电池管理系统)**:电池状态采集 +- **OBC(车载充电机)**:充电状态监测、充电指令控制 +- **电机控制器**:速度控制、扭矩输出控制 +- **灯光控制系统**:远近光灯、转向灯、刹车灯、自动驾驶指示灯控制 +- **ORIN(上层自动驾驶计算平台)**:接收自动驾驶指令、上报车辆状态 +- **遥控器**:接收手动驾驶指令、手自动模式切换 +- **机械臂控制器**:机械臂关节控制、作业工具控制 + +```mermaid +graph TD + RC --> VCU + ARM --> VCU + BMS--> VCU + VCU[VCU 控制中心] --> BMS[BMS 电池管理系统] + VCU --> OBC[OBC 车载充电机] + OBC --> VCU + ORIN --> VCU + VCU --> MOTOR[电机控制器] + VCU --> LIGHT[灯光控制系统] + VCU --> ORIN[ORIN 自动驾驶平台] + VCU --> RC[遥控器] + VCU --> ARM[机械臂控制器] + +``` + +## 2. 充电控制逻辑 +VCU负责整车充电流程的管理,通过CAN总线与BMS和OBC通信,收集两者状态并上报上层系统。 + +### 2.1 充电状态机 +```mermaid +stateDiagram-v2 + [*] --> OBC: 待充电状态 + OBC --> WAIT_FOR_CHARGE_CMD: 检测到OBC可充电 + ORIN --> CHARGING: 上层发送充电指令 + WAIT_FOR_CHARGE_CMD --> CHARGING: 收到上层充电指令 + WAIT_FOR_CHARGE_CMD --> CHARGING: 5分钟超时自动充电 + + OBC --> AUTO_CHARGE: 电量<25%且长时间停留在充电区域\n无上层控制 + AUTO_CHARGE --> CHARGING: 自动执行充电指令 + CHARGING --> AUTO_STOP_CHARGE: 电量充满 + AUTO_STOP_CHARGE --> OBC: 自动停止充电 +``` + +### 2.2 充电控制规则 +1. **充电触发条件**: + - 当VCU检测到无线OBC处于可充电状态时,进入等待充电指令状态 + - 优先等待上层(ORIN)发送充电开始指令 + - 若等待超时(5分钟),自动进入充电状态 + +2. **充电停止条件**: + - BMS上报电量充满后,VCU自动向OBC发送停止充电指令 + - 收到上层停止充电指令时,立即停止充电 + +3. **自动充电策略**: + - 车辆长时间停留在可充电区域且无上层控制指令时 + - 当电池电量低于25%时,自动执行充电指令 + - 电量充满后自动执行停止充电指令 + +## 3. 驾驶控制逻辑 +VCU支持两种驾驶模式:**自动驾驶模式**(上层ORIN控制)和**手动驾驶模式**(遥控器控制),遥控器控制优先级高于上层控制。 + +### 3.1 模式切换逻辑 +```mermaid +stateDiagram-v2 + [*] --> SBUS_WAIT: 遥控器未开机 + SBUS_WAIT --> AUTO_MODE: 上层ORIN连接并使能\n进入自动驾驶模式 + AUTO_MODE --> SBUS_CONNECTED: 遥控器开机 + SBUS_CONNECTED --> MANUAL_MODE: 遥控器手动模式\n不响应上层任何指令 + SBUS_CONNECTED --> AUTO_MODE: 遥控器自动模式\n上层可接管控制 +``` + +### 3.2 控制优先级规则 +1. **遥控器未开机时**: + - 等待上层ORIN连接并发送使能指令 + - 进入自动驾驶模式,响应ORIN的控制指令 + +2. **遥控器开机后**: + - 优先读取遥控器的手自动模式状态 + - **手动模式**:完全不响应上层ORIN的任何指令,所有控制以遥控器为准 + - **自动模式**:上层ORIN可以接管车辆控制 + +3. **高优先级刹车最高优先级**:遥控器独立刹车摇杆优先级高于所有其他控制指令,无论当前处于自动驾驶模式还是手动模式,只要拉动刹车摇杆,立即响应刹车指令,不受模式限制。 + +### 3.3 指令接收处理 +VCU通过CAN总线接收两类控制指令: + +#### 3.3.1 上层ORIN指令 +- 速度控制指令 +- 使能控制指令 +- 灯光控制指令(远近光灯) +- 驻车控制指令 + +#### 3.3.2 遥控器指令 +- 速度控制指令(单摇杆) +- 方向控制(单摇杆) +- 使能控制指令 +- 灯光控制指令 +- 手自动切换指令 +- 驻车控制指令 +- 模式切换指令 +- 机械臂各关节控制指令 +- 作业工具(滚刷)控制指令 +- 高优先级刹车控制指令 + +## 4. 电机控制逻辑 +### 4.1 遥控器单摇杆控制 +- 支持**原地转向**功能:摇杆左右方向控制转向,前后方向控制速度 +- 左右摇杆量直接对应转向角度,前后摇杆量对应目标速度 + +### 4.2 加减速限制 +为保证行驶平稳性,对电机输出进行如下限制: +1. **最大加速度限制**:加速度不超过预设最大值(可配置,默认0.5g) +2. **最大减速度限制**:减速度不超过预设最大值(可配置,默认0.3g) +3. **避免急停**:当遥控器速度指令突然变为0时,不直接切断动力输出,而是按照最大减速度平滑减速至停止 + +### 4.3 高优先级刹车控制 +遥控器配备独立高优先级刹车摇杆,为最高优先级控制输入,逻辑如下: +1. **全模式生效**:无论车辆当前处于自动驾驶模式还是手动驾驶模式,刹车摇杆指令均生效,不受当前控制模式限制 +2. **力度线性控制**:刹车摇杆拉动幅度对应刹车力度,幅度越大减速度越大,最大减速度不超过系统预设的最大减速度限值,实现缓慢刹车,避免急停 +3. **临时状态上报**:拉动刹车摇杆期间,VCU临时向上层ORIN上报车辆处于**手动模式**,同时屏蔽上层ORIN的速度控制指令,仅响应刹车指令 +4. **释放自动恢复**:刹车摇杆完全释放后,立即恢复原运行模式,向ORIN上报实际模式状态,恢复响应上层速度控制指令 +5. **不干涉其他控制**:刹车控制仅干预速度控制相关指令,不影响灯光、驻车、机械臂等其他控制功能 + +## 5. 灯光控制逻辑 +灯光控制暂时由VCU自主判断处理,无需上层系统干预。 + +### 5.1 控制列表 +| 灯光类型 | 控制逻辑 | +| -------- | -------------------- | +| 自动驾驶指示灯 | 自动驾驶模式开启时点亮,手动模式时熄灭 | +| 转向灯(左/右) | 根据转向指令自动开启,转向回正后自动关闭 | +| 刹车灯 | 车辆处于减速状态或驻车状态时点亮 | +| 远近光灯 | 接收上层或遥控器指令控制,默认不开启 | + +### + +## 6. 通信协议规范 +### 6.1 CAN通信矩阵(摘要) + +待补充 + +## 7. 故障处理与安全机制 +### 7.1 通信故障处理 +- 与BMS通信丢失:立即禁止充电,上报故障 +- 与OBC通信丢失:终止当前充电流程,上报故障 +- 与ORIN通信丢失:自动驾驶模式下减速停车,切换到待机状态 +- 与遥控器通信丢失:手动模式下减速停车,开启危险报警灯;机械臂手动模式下停止机械臂所有运动并锁定 + +### 7.2 安全保护机制 +待补充 +## 8. 配置参数(可调整) +| 参数名称 | 默认值 | 说明 | +| --------- | ----- | ------------------- | +| 充电指令等待超时 | 5分钟 | 检测到可充电后等待上层指令的最长时间 | +| 自动充电SOC阈值 | 25% | 低于该值时自动启动充电 | +| 最大加速度 | 1m/s² | 正向加速度上限 | +| 最大减速度 | 1m/s² | 反向加速度(减速)上限 | +| CAN通信超时阈值 | 500ms | 连续500ms未收到报文判定为通信丢失 | + +## 9. 机械臂控制逻辑 +VCU支持机械臂手动控制功能,通过遥控器切换操作模式,实现底盘控制与机械臂控制的复用,遵循**手动优先**的控制原则。 + +### 9.1 模式切换逻辑 +机械臂控制与底盘控制通过遥控器E拨杆进行切换,完全兼容《履带车T10遥控器协议与操作说明》: + +```mermaid +stateDiagram-v2 + [*] --> CHASSIS_MODE: E拨杆最左侧\n底盘控制模式 + CHASSIS_MODE --> ARM_MODE: E拨杆拨到最右侧\n切换到机械臂控制模式 + ARM_MODE --> CHASSIS_MODE: E拨杆拨到最左侧\n切换到底盘控制模式 + + state CHASSIS_MODE { + [*] --> CHASSIS_MANUAL: 手动模式 + [*] --> CHASSIS_AUTO: 自动模式 + } + + state ARM_MODE { + [*] --> ARM_MANUAL: 手动模式(默认) + ARM_MANUAL --> ARM_AUTO: A按键切换到自动模式\n上层可控制机械臂 + ARM_AUTO --> ARM_MANUAL: A按键切换到手动模式\n不响应上层指令 + } +``` + +### 9.2 控制优先级规则 +1. **手动模式优先**:无论机械臂处于何种状态,只要遥控器切换到机械臂手动控制模式,立即停止响应上层ORIN的机械臂控制指令 +2. **模式互斥**:E拨杆同一时间只能处于一种模式,底盘控制与机械臂控制不可同时操作 +3. **自动模式使能**:机械臂自动模式下,上层ORIN可以发送机械臂控制指令,VCU转发给机械臂控制器 + +### 9.3 遥控器机械臂操作映射(E拨杆最右侧) +完全遵循《履带车T10遥控器协议与操作说明》定义的操作逻辑: + +| 控制部件 | 功能 | 通道映射 | +|---------------|--------------------------|----------| +| 右摇杆X轴(x2) | 控制回转关节(joint1) | CH1 | +| 右摇杆Y轴(y2) | 控制动臂关节(joint4) | CH2 | +| 左摇杆Y轴(y1) | 控制横梁关节(joint3) | CH3 | +| 左摇杆X轴(x1) | 控制力臂关节(joint2) | CH4 | +| A按键 | 切换机械臂自动/手动控制模式 | CH7 | +| F拨杆 | 控制刷头上下移动(joint5) | CH6 | +| D轮盘 | 控制滚刷启停/转速 | CH10 | + +### 9.4 机械臂控制处理流程 +1. VCU实时接收遥控器CAN报文(ID范围:0x187~0x18A) +2. 解析E拨杆(CH5)数值判断当前操作模式 +3. **机械臂模式下**: + - 解析各通道摇杆量,转换为对应关节的目标角度/速度 + - 将控制指令通过CAN总线发送给机械臂控制器 + - 手动模式下直接转发遥控器指令,自动模式下转发上层ORIN指令 +4. **底盘模式下**: + - 忽略机械臂相关通道数据,保持机械臂当前状态 + - 执行底盘控制逻辑 + +### 9.5 安全保护机制 +1. **模式切换保护**:在机械臂运行过程中切换到底盘模式时,立即停止机械臂所有运动,保持当前位置 +2. **通信丢失保护**:遥控器通信丢失时,立即停止机械臂所有运动,进入锁定状态 +3. **急停保护**:收到急停指令时,立即切断机械臂动力输出 + +## 10. 通信协议补充 +### 10.1 遥控器CAN通信扩展 +| CAN ID | 发送方 | 接收方 | 报文内容 | 周期 | +|--------|--------|--------|----------|------| +| 0x187 | 遥控器 | VCU | 通道1-4数据(摇杆) | 10ms | +| 0x188 | 遥控器 | VCU | 通道5-8数据(拨杆、按键) | 10ms | +| 0x189 | 遥控器 | VCU | 通道9-10数据(轮盘) | 10ms | +| 0x18A | 遥控器 | VCU | 保留 | 10ms | +| 0x18B | 遥控器 | VCU | 校验帧 | 10ms | + diff --git a/工作/nav2 优缺点.md b/工作/nav2 优缺点.md new file mode 100644 index 0000000..a01b773 --- /dev/null +++ b/工作/nav2 优缺点.md @@ -0,0 +1,6 @@ +控制相关参数没有按速度区间机制,需要自己实现 +rtk精度行走是够的,但是目前看会有5-8cm的跳变,所以充电还是需要用docking server配合视觉或者雷达精确定位,加上限位和触点开关之类的。 + +体量小,开发快,资料够多。 + +route server支持大地图 \ No newline at end of file diff --git a/工作/履带车T10遥控器协议与操作说明.md b/工作/履带车T10遥控器协议与操作说明.md new file mode 100644 index 0000000..738740e --- /dev/null +++ b/工作/履带车T10遥控器协议与操作说明.md @@ -0,0 +1,75 @@ + +## 1. 硬件概述 +本文档描述云卓T10遥控器通过SBUS转CAN模块输出的CAN通信协议及操作逻辑。遥控器布局参考下图: + +![[Pasted image 20260402112914.png|350]] +![[Pasted image 20260402112951.png|369]] +--- + +## 2. CAN通信协议规范 +### 2.1 基础参数 +- CAN ID范围:`0x187` ~ `0x18A`(共4个ID,每个ID对应4个通道数据) +- 比特率:500K +- 数据长度:每帧8字节,包含4个通道值,每个通道占2字节 +- 字节序:大端模式(第一字节为高位字节) +- 通道值范围: + - 最小值:`0x011A` (十进制 282) + - 中间值:`0x03EA` (十进制 1002) + - 最大值:`0x06BA` (十进制 1722) +- 开关量特性:A/B按键为开关量,开关打开时输出最大值,关闭时输出最小值 + +### 2.2 帧结构 + +| CAN ID | 0-1 | 2-3 | 4-5 | 6-7 | +| ------ | --- | ---- | --- | --- | +| 0x187 | CH1 | CH2 | CH3 | CH4 | +| 0x188 | CH5 | CH6 | CH7 | CH8 | +| 0x189 | CH9 | CH10 | 保留 | 保留 | +| 0x18A | 保留 | 保留 | 保留 | 保留 | +| 0x18B | 校验 | | | | +18B高位为数字通道和状态位,低位为前33位累加和校验。 + +## 3. 遥控器通道映射表 +| 控制部件 | 通道编号 | 说明 | +| --------- | ---- | --------- | +| 右摇杆X轴(x2) | CH1 | 横向数值,左小右大 | +| 右摇杆Y轴(y2) | CH2 | 纵向数值,上小下大 | +| 左摇杆Y轴(y1) | CH3 | 纵向数值,下小上大 | +| 左摇杆X轴(x1) | CH4 | 横向数值,左小右大 | +| E拨杆 | CH5 | 三档,左小右大 | +| F拨杆 | CH6 | 三档,左小右大 | +| A按键 | CH7 | 开关量 | +| B按键 | CH8 | 开关量 | +| C轮盘 | CH9 | 左小右大 | +| D轮盘 | CH10 | 左小右大 | + +--- + +## 4. 操作模式说明 +遥控器由E拨杆位置切换两种工作模式: + +### 4.1 底盘控制模式(E拨杆拨到最左侧,通道5输出最小值) +| 控制部件 | 功能 | +| --------- | ----------- | +| 左摇杆X轴(x1) | 控制底盘左右转向 | +| 左摇杆Y轴(y1) | 控制底盘前后移动 | +| A按键 | 切换自动/手动控制模式 | +| B按键 | 切换驻车状态 | +| F拨杆 | 切换前灯远近光 | + +### 4.2 机械臂控制模式(E拨杆拨到最右侧,通道5输出最大值) +| 控制部件 | 功能 | +| --------- | ---------------- | +| 右摇杆X轴(x2) | 控制回转关节(joint1) | +| 右摇杆Y轴(y2) | 控制动臂关节(joint4) | +| 左摇杆Y轴(y1) | 控制横梁关节(joint3) | +| 左摇杆X轴(x1) | 控制力臂关节(joint2) | +| A按键 | 切换自动/手动控制模式 | +| F拨杆 | 控制刷头上下移动(joint5) | +| D轮盘 | 控制滚刷启停/转速 | + +--- + +## 5. 版本信息 +- 文档版本:V1.0 +- 最后更新:2026-04-02 diff --git a/工作/履带车T10遥控器协议与操作说明.pdf b/工作/履带车T10遥控器协议与操作说明.pdf new file mode 100644 index 0000000..be4f4ed Binary files /dev/null and b/工作/履带车T10遥控器协议与操作说明.pdf differ diff --git a/工作/机械臂分析.md b/工作/机械臂分析.md new file mode 100644 index 0000000..e69de29 diff --git a/技术趋势/AI编译器现状与前景.md b/技术趋势/AI编译器现状与前景.md new file mode 100644 index 0000000..b64d099 --- /dev/null +++ b/技术趋势/AI编译器现状与前景.md @@ -0,0 +1,182 @@ +# AI 编译器现状与前景 + +> 2026-08-05 分析笔记。源自一个判断:大模型时代模型结构收敛、数量变少,传统 AI 编译器必要性下降,"只需适配特定子网络深入优化即可"——这个判断对一半。 + +--- + +## 背景:原判断 + +作者背景:做过编译器工作,TVM 0.6 魔改 + 接触过 MLIR。 + +原判断: +- 大模型时代,模型结构越来越固定(decoder-only Transformer 一统) +- 模型数量远少于传统 CNN 时代 +- 传统 AI 编译器(通用图级自动优化)必要性下降 +- 只需适配特定子网络,深入优化即可 + +--- + +## 一、判断对的部分:通用图编译器退潮 + +在**图级通用编译**这一层,判断成立,有实证: + +### OctoML 案例(最重要的证据) + +- NVIDIA 2024年5月收购 OctoML(TVM 团队),官方理由是"拿到能把固定硅片上最后几个点性能挤出来的人" +- **结果相反**:编译流水线产品被逐步废弃,客户流向 vLLM 等 serving-first 引擎 +- **结论:编译优先输给了服务优先**——生产 LLM 系统真正花时间的是低 TTFT、持续吞吐、API 契约,而不是"把模型编译成最优 artifact" + +### AOT → JIT 的转移 + +| | AOT(传统编译器) | JIT(2026 主流) | +|---|---|---| +| 模式 | 模型进 → 优化 passes → 编译产物出 | 运行时按需编译 kernel,首次启动缓存 | +| 代表 | TVM、TensorRT-LLM | FlashInfer、DeepGEMM、Triton | +| 部署速度 | TensorRT-LLM 构建 engine 需数小时 | vLLM 加载 HF 模型只需几分钟 | + +### CNN vs LLM 的模型量 + +- CNN 时代:几百上千种网络结构 → 通用图编译"一套处理任意图"有价值 +- LLM 时代:decoder-only 一统,结构高度收敛 → 为"任意图"做的通用优化确实浪费 + +--- + +## 二、判断的偏差:"AI 编译器"分裂成了四个层 + +> 核心偏差:把"AI 编译器"等同于 TVM 0.6 式的通用图编译器。 +> 实际 2026 年编译器工作量没有变少,而是转移到四个更深更专的层。 + +### 层 1:Kernel 层——最热战场 + +LLM 时代性能关键算子的集合**比 CNN 时代更丰富**: + +| 算子/技术 | 为什么难 | +|---|---| +| FlashAttention / MLA | 每次新注意力变体 = 新 kernel 的数月专家工作 | +| MoE 路由 + GEMM | 专家调度、跨卡通信;vLLM 的 MoE backend 从 FlashInfer 切到 Triton(H200 更快) | +| FP8 / FP4 / NVFP4 量化 GEMM | 新数值格式把旧 cost model 和调度规则**全部作废** | +| 长上下文 / PagedAttention | 变长序列、内存受限的 kernel 调度 | + +当前 Kernel 层的生态谱系(从高层 DSL 到底层): + +``` +Triton(事实标准,高层 tile 抽象) + ↓ +TileLang / Helion(布局自动推断) + ↓ +CuTe DSL(CUTLASS v4,可组合布局抽象) + ↓ +TIRx / TLX(硬件原生,显式 orchestration) + ↓ +CUDA / PTX(手工极限优化) +``` + +### 层 2:推理引擎层——"编译器/运行时边界模糊" + +**LLM 推理编译已被定义为独立学科**:传统编译器五层框架(图→kernel→内存→运行时调度)被在线调度吸收。 + +- 动态形状(变长序列、KV cache) +- chunked prefill、continuous batching +- 这些调度问题**本质上变成了编译问题** + +代表:vLLM、SGLang、TensorRT-LLM、llama.cpp。 + +2026 实战数据: +- vLLM V1 引擎比 V0 快 1.5~2×(异步调度、chunked prefill、torch.compile 集成) +- vLLM 默认 MoE backend 从 FlashInfer 切到 Triton:H200 上 57,821 vs 55,700 tokens/s +- TensorRT-LLM 高并发(32+ 并发)时仍快 10~30%,但需数小时 build engine + +### 层 3:硬件使能层——传统编译器反而吃香 + +反转点:**通用模型少,但硬件爆发式碎片化**。 + +- NVIDIA Blackwell、AMD MI300X、华为昇腾、寒武纪、国产 ASIC +- 非 NVIDIA 芯片没有厂商 kernel 库 → **编译栈是必需的** +- 国内芯片编译团队从"建设期"进入"换血期":要求 codegen 优化、内存规划、target-specific 调度的深度人才 +- TVM/MLIR"一套栈、多后端"思路在这一层真正兑现价值 + +### 层 4:LLM 生成 kernel——角色重塑 + +2025-2026 最大变量:**LLM agent 成为 kernel 生成器和编译器优化器**。 + +| 系统 | 结果 | +|---|---| +| **KernelEvolve**(Meta,已部署) | 480 个算子-平台组合 100% 正确率,1.25~17× 加速,开发时间从数周降到数小时 | +| **KernelBench** | LLM kernel 能力基准 | +| **AutoTriton / TritonRL / KernelLLM** | RL 驱动的 Triton 生成 | +| **Compiler-R1 / REASONING COMPILER**(NeurIPS 2025) | RL 驱动的编译自动调优 | + +> 意义:未来编译器工程师核心技能从"手写 kernel"变为"**引导 agent 搜索 + 验证正确性 + 设计搜索空间**"。 + +--- + +## 三、反驳"只需适配特定子网络" + +策略对,深度被低估: + +- **"只优化少量关键算子"是对的**——这正是 vLLM/TensorRT-LLM 的做法 +- 但"只需"严重低估深度:把 FlashAttention-4 或 MoE kernel 在 B200 调到峰值是**数周专家工作** +- **动态形状是关键分水岭**:静态形状下融合是"规则问题",动态形状下是"开放问题"(广播开销、索引计算、codegen 分支)。2026 人才市场把"动态形状编译"列为 LLM 推理团队硬性要求 +- 值钱的是**精通动态形状 pass 设计、memory-bound 优化、新数值格式**的人,不是"会写 dialect 定义和基本 lowering"的人 + +MLIR 生态(2026 年已是"编译器基础设施的 Linux"): +- torch.compile (Inductor) 是 MLIR 思想设计 +- Google XLA 已迁移到 MLIR 底层 +- IREE 是纯 MLIR 栈 +- 需求已从"懂 dialect 机制"转向"**自定义 pass 流水线设计、图融合策略、跨 IR 优化**" + +--- + +## 四、前景判断(2026) + +``` +通用图编译器(TVM 全自动调优式) ↘ 退潮,仅存于特定 niche +Kernel DSL(Triton/CuTe/TileLang) ↗ 繁荣,LLM 推理事实标准 +推理引擎内部编译(vLLM/SGLang) ↗ 最热,编译器×分布式交叉岗位稀缺 +硬件使能编译栈(昇腾/AMD/寒武纪) ↗ 确定性增长,国产芯片刚需 +LLM agent 生成 kernel ↗ 爆发前夜,重塑工程师角色 +``` + +### 关键结论 + +> **AI 编译器没有死,死的是"通用图编译"这个窄定义。** + +- AI 推理支出 2026 年已超过训练 +- 编译器工程师是 AI 基础设施链上最稀缺岗位之一 +- 能力栈从"覆盖任意图"转向"**少量关键算子做到极致的深度 + 动态形状 + 新硬件 + 新数值格式**" + +--- + +## 五、职业建议(针对本笔记作者背景) + +作者技能:TVM 0.6(Relay/TIR/AutoTVM 时代)+ MLIR。 + +| 技能 | 2026 年变现路径 | +|---|---| +| MLIR 了解 | 深入 torch.compile/Inductor 的 pass 设计、动态形状融合 | +| TVM 调度/调优思想 | 转向 Triton/CUTLASS——AutoTVM/Ansor 的调优心智模型可迁移 | +| 编译原理底子(IR/pass/调度) | vLLM/SGLang 内部,编译器×分布式调度是稀缺交叉 | +| 多后端思维 | 国产芯片(昇腾 CANN、寒武纪)使能,"适配子网络"直觉在此是核心竞争力 | + +**一句话建议**: +> 不守"通用编译框架"这条船;把"适配特定子网络深入优化"做深到极致——但"深"是指**动态形状 + 新数值格式 + 新硬件架构**三个维度,而不是 TVM 0.6 时代的静态图自动调优。编译功底在这三个维度上直接可迁移,是"只会写 PyTorch 的 ML 工程师"够不着的护城河。 + +--- + +## 参考资料 + +- [LLM Inference Compiler Panorama(推理编译独立成领域)](https://arxiv.org/pdf/2512.23236v1) +- [TIRx:TVM 上的新 kernel DSL(2026-06)](https://tvm.apache.org/2026/06/22/tirx) +- [vLLM 切换 Triton MoE backend(PR #44220)](https://github.com/vllm-project/vllm/pull/44220) +- [AI Inference Engines 2026 全景](https://www.youngju.dev/blog/culture/2026-05-16-ai-inference-engines-2026-vllm-sglang-llama-cpp-tgi-tensorrt-llm-mlx-mistralrs-deepspeed-aphrodite-deep-dive.en) +- [KernelEvolve:Meta 生产级 LLM kernel 生成](https://www.ivoox.com/llm-inference-compiler-panorama-research-and-engineering-evolution-audios-mp3_rf_176267639_1.html) + +## 相关链接 + +- [[大模型架构基础]] — 编译的对象:Transformer 结构 +- [[DeepSeek V4 系列]] — 最新模型的 FP8/NVFP4、DSpark 都是 kernel 层优化 +- [[FFN 前馈网络详解]] — MoE/SwiGLU 是最热的 kernel 优化对象 + +--- + +*最后更新:2026-08-05* diff --git a/自建服务/Gitea部署指南.md b/自建服务/Gitea部署指南.md new file mode 100644 index 0000000..5ed5c34 --- /dev/null +++ b/自建服务/Gitea部署指南.md @@ -0,0 +1,104 @@ +# Gitea 部署指南 + +> 2026-08-13 记录。自托管轻量 Git 服务,个人代码仓库,Web 用 Caddy 反代套 HTTPS。域名域名 `git.hyonglin.top`。 + +--- + +## 选型 + +| 方案 | 是否选用 | 原因 | +|---|---|---| +| **Gitea** | ✅ | Go 单二进制,轻量(~50–100MB),功能全(仓库/Issue/PR/Actions/Package),社区活跃、安全更新及时 | +| Gogs | ❌ | Gitea 的 fork 前身,开发停滞,新项目不推荐 | +| 裸仓库+SSH | ❌ | 无 Web 界面 | + +> Gitea 是 Gogs 的 fork(社区驱动),新项目无脑选 Gitea;若更在意「纯社区治理」可选 Forgejo。 + +--- + +## docker-compose 服务 + +`silverbullet/docker-compose.yml`: + +```yaml + gitea: + image: gitea/gitea:latest + container_name: gitea + restart: unless-stopped + environment: + - USER_UID=1000 + - USER_GID=1000 + - GITEA__server__ROOT_URL=https://git.hyonglin.top/ + - GITEA__server__DOMAIN=git.hyonglin.top + - GITEA__server__SSH_DOMAIN=git.hyonglin.top + - GITEA__server__SSH_PORT=2222 + ports: + - "2222:22" # SSH clone 用(服务器 22 已被 SSH 占用,故映射 2222) + volumes: + - ./gitea:/data + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro +``` + +- Web(3000)不映射端口,由 Caddy 反代 `gitea:3000` +- SSH 需映射 `2222:22`,因为宿主机 22 被 OpenSSH 占用 + +## Caddy 反代 + +`silverbullet/Caddyfile` 加一段: + +```caddyfile +# Git 服务 +git.hyonglin.top { + tls { + dns cloudflare {env.CF_API_TOKEN} + } + reverse_proxy gitea:3000 +} +``` + +## compose 部署 + +```bash +docker compose up -d gitea +docker compose up -d --force-recreate caddy # 让 caddy 加载新站点 +``` + +--- + +## 首次安装(web 向导) + +打开 `https://git.hyonglin.top` 走安装向导: + +- **数据库**:默认 `SQLite3`(个人用足够) +- **域名/URL**:环境变量已预设(`git.hyonglin.top`),保持默认 +- **SSH 端口**:`2222` +- **管理员账号**:设置用户名/邮箱/密码 +- 点「安装 Gitea」 + +验证安装完成: + +```bash +# app.ini 应已锁定安装 +grep INSTALL_LOCK /home/ubuntu/silverbullet/gitea/gitea/conf/app.ini # → true + +# 确认管理员存在 +docker compose exec -T gitea su git -c "gitea admin user list" +``` + +--- + +## 使用 + +- **Web**:登录 `https://git.hyonglin.top` 建仓库 +- **HTTPS clone**:`git clone https://git.hyonglin.top/用户名/仓库.git` +- **SSH clone**:`git clone git@git.hyonglin.top:2222/用户名/仓库.git`(需安全组放行 TCP 2222) +- **备份**:备份 `silverbullet/gitea` 目录(含数据库和所有仓库) + +--- + +## 相关链接 + +- [[主页与Caddy反向代理]] — git.hyonglin.top 的 HTTPS 入口 +- [[frp内网穿透部署指南]] — 本服务器其他自建服务 +- [Gitea 官方文档](https://docs.gitea.com/zh-cn/) \ No newline at end of file diff --git a/自建服务/Silverbullet部署指南.md b/自建服务/Silverbullet部署指南.md new file mode 100644 index 0000000..fd16f0e --- /dev/null +++ b/自建服务/Silverbullet部署指南.md @@ -0,0 +1,219 @@ +# Silverbullet 部署指南 + +> 2026-08-05 记录。目标:在远程 Linux 服务器上用 Docker 部署自托管笔记服务,实现"随时随地在任意设备用浏览器查看编辑笔记"。 + +--- + +## 背景与选型 + +**需求**:远程服务器部署,随时随地任意设备查看、编辑笔记。 + +**选型结论**:Silverbullet(浏览器直接编辑 + Linux/Docker)。 + +### 为什么选 Silverbullet + +- 任何设备浏览器打开网址即可**查看 + 编辑**,无需安装 App +- 支持 `[[]]` 双链、反向链接(**与 Obsidian 语法兼容**,现有笔记可直接用) +- 笔记是纯 Markdown 文件,存在服务器目录,备份 = 复制文件夹 +- PWA 支持,手机浏览器可离线编辑 +- Docker 一条命令部署,开源 + +### 备选:code-server(VS Code Web) + +如果更想要完整 VS Code 体验,用 codercom/code-server。缺点:移动端体验差、无双链支持。**先用 Silverbullet,不够再补。** + +--- + +## 一、服务器部署 + +### 创建 docker-compose.yml + +```yaml +services: + silverbullet: + image: ghcr.io/silverbulletmd/silverbullet:latest + container_name: silverbullet + restart: unless-stopped + ports: + - "3000:3000" + volumes: + - ./space:/space # 笔记存储目录,备份就是复制这个文件夹 + environment: + - SB_USER=admin:改成你的强密码 # 登录认证,必填! +``` + +### 启动 + +```bash +docker compose up -d +``` + +访问 `http://服务器IP:3000` → 输入 admin/密码 → 完成。 + +### 常用环境变量 + +| 变量 | 说明 | 默认 | +|---|---|---| +| `SB_FOLDER` | Markdown 文件目录 | `/space` | +| `SB_PORT` | 内部端口 | `3000` | +| `SB_USER` | Basic auth(`user:pass`) | 无认证 | +| `SB_AUTH_TOKEN` | Bearer token API 访问 | 无 | +| `SB_READ_ONLY` | 只读模式 | `0` | + +--- + +## 二、迁移现有笔记 + +本机笔记在 `d:\onedrive\note`(Windows),用 Git Bash 一次性传到服务器: + +```bash +# 服务器上先建目录 +ssh user@server "mkdir -p /path/to/space" + +# rsync 上传(排除 Obsidian 配置目录,Silverbullet 用不上) +rsync -avP --exclude ".obsidian" "/d/onedrive/note/" user@server:/path/to/space/ +``` + +--- + +## 三、HTTPS + 域名(强烈建议) + +裸 HTTP 下密码明文传输,不安全。用 Caddy 做反向代理 + 自动 TLS 证书(Let's Encrypt)。 + +### 前提条件 + +- 一个已备案/可用的域名,如 `notes.yourdomain.com` +- 域名 A 记录已指向服务器公网 IP +- 服务器 80 和 443 端口未被占用(云服务器需在安全组放行这两个端口) + +### 整合后的 docker-compose.yml + +将 Caddy 和 Silverbullet 放在同一个 compose 文件中,让它们共享同一个 Docker 网络,容器间用服务名互相访问: + +```yaml +services: + silverbullet: + image: ghcr.io/silverbulletmd/silverbullet:latest + container_name: silverbullet + restart: unless-stopped + volumes: + - ./space:/space + environment: + - SB_USER=admin:改成你的强密码 + # 不暴露 ports,只允许 Caddy 通过内部网络访问 + + caddy: + image: caddy:latest + container_name: caddy + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile + - caddy_data:/data # 证书和密钥持久化,避免重启重新申请 + - caddy_config:/config # Caddy 自身配置 + +volumes: + caddy_data: + caddy_config: +``` + +> **关键**:`caddy_data` 和 `caddy_config` 用 named volume 而非 bind mount,避免权限问题,且证书重启不丢失。 + +### Caddyfile 配置 + +在 `docker-compose.yml` 同级目录创建 `Caddyfile`(纯文本,无后缀): + +```caddyfile +# 基础版:自动 HTTPS + 反向代理 +notes.yourdomain.com { + reverse_proxy silverbullet:3000 +} +``` + +**常用增强配置**: + +```caddyfile +notes.yourdomain.com { + # 反向代理 + reverse_proxy silverbullet:3000 + + # 访问日志(排查问题时打开) + log { + output file /var/log/caddy/access.log + } + + # 限制请求体大小(上传大文件时调大) + request_body { + max_size 50MB + } + + # 安全头(可选) + header { + X-Content-Type-Options nosniff + X-Frame-Options DENY + -Server + } +} +``` + +### 启动与验证 + +```bash +# 启动 +docker compose up -d + +# 查看 Caddy 日志(确认证书申请是否成功) +docker compose logs caddy -f +``` + +正常日志中应能看到类似 `certificate obtained successfully` 的输出。然后浏览器访问 `https://notes.yourdomain.com` 即可。 + +### 排错 + +| 问题 | 检查项 | +|---|---| +| 证书申请失败 | 确认域名 A 记录已生效(`dig notes.yourdomain.com` 或 `nslookup`),且 80 端口能从公网访问 | +| 502 Bad Gateway | `docker compose ps` 确认 silverbullet 容器在运行;确认 Caddyfile 中 `reverse_proxy` 的目标容器名与 compose 中 service 名一致 | +| 端口被占用 | 如果服务器已有 nginx/apache,先停掉再启 Caddy,或让 Caddy 监听其他端口 | +| 国内服务器 | 80/443 端口需备案;若无备案可用非标端口 + DNS 验证,但 Caddy 默认 HTTP-01 验证仍需 80 端口可达 | + +> 无域名临时方案:frp / 路由侠等内网穿透工具把 3000 端口暴露出去。 + +--- + +## 四、数据备份 + +笔记是纯 Markdown → 备份 = 压缩目录: + +```bash +# 手动备份 +tar czf notes-backup-$(date +%F).tar.gz /path/to/space/ + +# cron 定时备份 + 保留最近 7 份 +0 3 * * * tar czf /backup/notes-$(date +%F).tar.gz /path/to/space/ && ls -t /backup/notes-*.tar.gz | tail -n +8 | xargs rm -f +``` + +--- + +## 五、使用方式转变(关键) + +选浏览器编辑 → **服务器目录成为唯一权威版本**,本地 OneDrive 降级为离线备份: + +| 场景 | 操作 | +|---|---| +| 日常编辑 | 浏览器打开 Silverbullet,直接改服务器文件 | +| 本地离线备份 | `rsync user@server:/path/to/space/ /d/onedrive/note/` | +| 多设备 | 全部走浏览器,无需装任何东西 | + +--- + +## 相关链接 + +- [[大模型架构基础]] — 本笔记库的正式学习内容 +- [[AI编译器现状与前景]] — 技术趋势分析 + +--- + +*最后更新:2026-08-05* diff --git a/自建服务/frp内网穿透部署指南.md b/自建服务/frp内网穿透部署指南.md new file mode 100644 index 0000000..396d780 --- /dev/null +++ b/自建服务/frp内网穿透部署指南.md @@ -0,0 +1,218 @@ +# frp 内网穿透部署指南 + +> 2026-08-13 更新。目标:通过云服务器(公网 IP `58.87.87.208`)随时随地访问家里多台机器的 SSH 和 RDP,统一用域名 `hyonglin.top` + 端口区分。 + +--- + +## 背景与方案 + +**需求**:家里机器在 NAT 内网、没有公网 IP,想在任意地点 SSH 进去、远程桌面操作。 + +**选型结论**:frp(Fast Reverse Proxy),成熟的内网穿透工具。 + +- 家里机器(内网)主动反向连到云服务器,云服务器监听公网端口转发进来 +- 一个服务端(frps)对多个客户端(frpc),加机器只需加端口,服务端不用动 +- Go 编写,单文件二进制,Linux/Windows 通用,systemd 管理开机自启 + +### 架构 + +``` +你(任意地点) 云服务器 frps 家里机器 frpc(可多台) + │ │ │ + ├─SSH hyonglin.top:2201──▶│─监听 2201───────────▶│─▶ pc01:22 + ├─SSH hyonglin.top:2202──▶│─监听 2202───────────▶│─▶ pc02:22 + ├─RDP hyonglin.top:3389──▶│─监听 3389───────────▶│─▶ pc01:3389 + ├─RDP hyonglin.top:3390──▶│─监听 3390───────────▶│─▶ pc02:3389 + │ └─frpc 主动连 bindPort 7000◀─┘ +``` + +> 域名只解析到 IP,**端口才是区分机器的关键**。RDP 不能共用 3389(TCP 层没有域名概念),但 frp 的 `remotePort` 独立于本机 `localPort`,本机 RDP 端口保持 3389 不用改。 + +--- + +## 端口规划 + +| 机器 | SSH(remotePort) | RDP(remotePort) | 本机端口 | +|---|---|---|---| +| pc01 | 2201 | 3389 | 22 / 3389 | +| pc02 | 2202 | 3390 | 22 / 3389 | +| 新增机器 | 2203 | 3391 | … | + +固定端口:frps 客户端连接 `7000`、管理面板 `7500`。 + +--- + +## 一、服务端 frps 部署(云服务器) + +### 下载与安装 + +```bash +# 下载(GitHub 慢时走镜像 ghfast.top) +wget https://ghfast.top/https://github.com/fatedier/frp/releases/download/v0.65.0/frp_0.65.0_linux_amd64.tar.gz +tar xzf frp_0.65.0_linux_amd64.tar.gz + +sudo cp frp_0.65.0_linux_amd64/frps /usr/local/bin/ +sudo mkdir -p /etc/frp +``` + +### 服务端配置 `/etc/frp/frps.toml` + +```toml +bindPort = 7000 # frpc 连接端口 +auth.token = "0ae2664b411c41645e5c9ab6779724d4" # 客户端认证令牌(frpc 必须一致) + +# 管理面板 +webServer.addr = "0.0.0.0" +webServer.port = 7500 +webServer.user = "admin" +webServer.password = "Admin-0ae2664b" + +# 日志 +log.to = "/var/log/frps.log" +log.level = "info" +log.maxDays = 7 +``` + +### systemd 服务 `/etc/systemd/system/frps.service` + +```ini +[Unit] +Description=frp server +After=network.target + +[Service] +Type=simple +ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now frps +systemctl status frps # active (running) +``` + +--- + +## 二、客户端 frpc 部署(家里机器) + +### 客户端配置 `/etc/frp/frpc.toml` + +以 pc01 为例: + +```toml +serverAddr = "hyonglin.top" +serverPort = 7000 +auth.token = "0ae2664b411c41645e5c9ab6779724d4" + +# SSH:服务器 2201 → 本机 22 +[[proxies]] +name = "pc01-ssh" +type = "tcp" +localIP = "127.0.0.1" +localPort = 22 +remotePort = 2201 + +# RDP:服务器 3389 → 本机 3389 +[[proxies]] +name = "pc01-rdp" +type = "tcp" +localIP = "127.0.0.1" +localPort = 3389 +remotePort = 3389 +``` + +> 加第二台(pc02):把 `name` 换成 `pc02-*`、`remotePort` 换成 `2202`/`3390`,`serverAddr`/`token` 不变即可。 + +### 安装(frpc 二进制 + systemd) + +```bash +sudo install -m 755 ~/frpc /usr/local/bin/frpc +sudo mkdir -p /etc/frp +sudo cp ~/frpc.toml /etc/frp/frpc.toml +sudo cp ~/frpc.service /etc/systemd/system/frpc.service +sudo systemctl daemon-reload +sudo systemctl enable --now frpc +systemctl status frpc # active (running) +``` + +--- + +## 三、家里开启 SSH 和 RDP 服务 + +### SSH + +```bash +sudo apt update && sudo apt install -y openssh-server +sudo systemctl enable --now ssh +``` + +### RDP(Ubuntu 内置,无需装 xrdp) + +- 打开 **设置 → 系统 → 远程桌面** +- 开启 **远程登录**(Remote Desktop / RDP)开关,记下用户名密码 +- 端口默认 3389 + +> ⚠️ Ubuntu 内置 RDP 依赖**已登录的图形会话**。重启后停在登录界面、无人登录时 RDP 连不上。若要无人值守,需换 xrdp 方案。 + +--- + +## 四、云安全组放行端口(关键坑) + +**最容易漏的一步**:云服务商控制台的「防火墙/安全组」默认只开 22/80/443,需手动放行 TCP: + +``` +7000(frps 连接)、2201/2202(SSH 转发)、3389/3390(RDP 转发) +``` + +> 服务器内部 `ufw` 是 inactive,iptables 只黑名单了若干恶意 IP,不影响端口;问题出在**云控制台安全组**,与服务器内防火墙无关。 + +> 7500(frps 管理面板)走 `frp.hyonglin.top` HTTPS 后,建议在安全组**撤销 7500 的公网放行**,避免明文暴露。 + +--- + +## 五、验证与使用 + +```bash +# 服务器端确认 frpc 已登录、代理已监听 +ss -tlnp | grep -E '2201|2202|3389|3390' +sudo tail -f /var/log/frps.log # 应看到 client login / new proxy success +``` + +连接方式(统一 hyonglin.top + 端口): + +| 目标 | 命令 | +|---|---| +| pc01 SSH | `ssh 用户名@hyonglin.top -p 2201` | +| pc01 RDP | 远程桌面连 `hyonglin.top:3389` | +| pc02 SSH | `ssh 用户名@hyonglin.top -p 2202` | +| pc02 RDP | 远程桌面连 `hyonglin.top:3390` | + +管理面板:`https://frp.hyonglin.top`(admin / Admin-0ae2664b) + +--- + +## 排错记录 + +| 症状 | 原因 | 解决 | +|---|---|---| +| frpc 状态 active 但 frps 日志无 login 记录 | 云安全组没放行 7000 | 控制台放行 7000 及转发端口 | +| `login to server failed` | token 不一致 | 检查 frpc/frps 的 auth.token 是否相同 | +| 2201 没监听 | frpc 没启动或代理注册失败 | `journalctl -u frpc -n 50` 看报错 | + +--- + +## 相关链接 + +- [[主页与Caddy反向代理]] — 主页/面板的 HTTPS 入口 +- [[sshwifty网页SSH终端]] — 浏览器里连 SSH +- [[Silverbullet部署指南]] — 本服务器自建服务 +- [frp官方文档](https://gofrp.org/zh-cn/) + +--- + +*最后更新:2026-08-13* diff --git a/自建服务/sshwifty网页SSH终端.md b/自建服务/sshwifty网页SSH终端.md new file mode 100644 index 0000000..e671a61 --- /dev/null +++ b/自建服务/sshwifty网页SSH终端.md @@ -0,0 +1,84 @@ +# sshwifty 网页 SSH 终端 + +> 2026-08-13 记录。网页版通用 SSH 客户端,浏览器里填主机/端口/账号即可连接任意机器。Go 单二进制,内存占用 ~10–30MB。 + +--- + +## docker-compose 服务 + +```yaml + sshwifty: + image: niruix/sshwifty:latest + container_name: sshwifty + restart: unless-stopped + environment: + - SSHWIFTY_CONFIG=/etc/sshwifty.conf.json # 指向配置文件 + volumes: + - ./sshwifty.conf.json:/etc/sshwifty.conf.json +``` + +不暴露端口,由 Caddy 反代 `sshwifty:8182`(WebSocket,Caddy 默认支持),入口 `https://ssh.hyonglin.top`。 + +--- + +## 配置文件 sshwifty.conf.json(含预设主机) + +```json +{ + "SharedKey": "hylssh0813", + "Servers": [ + { "ListenInterface": "0.0.0.0", "ListenPort": 8182 } + ], + "Presets": [ + { + "Title": "pc01", + "Type": "SSH", + "Host": "hyonglin.top:2201", + "Meta": { "User": "ylhan", "Encoding": "utf-8", "Authentication": "Password" } + }, + { + "Title": "pc02", + "Type": "SSH", + "Host": "hyonglin.top:2202", + "Meta": { "User": "ylhan", "Encoding": "utf-8", "Authentication": "Password" } + }, + { + "Title": "云服务器", + "Type": "SSH", + "Host": "hyonglin.top:22", + "Meta": { "User": "ubuntu", "Encoding": "utf-8", "Authentication": "Password" } + } + ], + "OnlyAllowPresetRemotes": false +} +``` + +> 端口写在 `Host` 里用 `host:port`,没有单独的 Port 字段。`OnlyAllowPresetRemotes: true` 可限制只连预设主机。改完配置 `docker compose up -d sshwifty` 重启生效。 + +--- + +## 使用 + +1. 打开 `https://ssh.hyonglin.top`,输入 SharedKey 密码 +2. 预设主机点一下即连,也可手动填任意主机: + +| 预设 | 目标 | +|---|---| +| pc01 | `hyonglin.top:2201` | +| pc02 | `hyonglin.top:2202` | +| 云服务器 | `hyonglin.top:22` | + +--- + +## 坑:Known Remotes 不跨设备 + +Known Remotes(已知主机)存在浏览器 `localStorage`,换机器/换浏览器/清缓存都会丢,**没有服务端存储**。 + +要跨设备固定入口,就用上面的 **Presets**(服务端配置,所有机器通用)。 + +--- + +## 相关链接 + +- [[frp内网穿透部署指南]] — SSH/RDP 端口转发 +- [[主页与Caddy反向代理]] — ssh.hyonglin.top 的 HTTPS 入口 diff --git a/自建服务/主页与Caddy反向代理.md b/自建服务/主页与Caddy反向代理.md new file mode 100644 index 0000000..63c84f7 --- /dev/null +++ b/自建服务/主页与Caddy反向代理.md @@ -0,0 +1,127 @@ +# 主页与 Caddy 反向代理 + +> 2026-08-13 记录。用 Caddy 给自建服务套 HTTPS,并做一个主页统一列出服务链接。域名都在 Cloudflare 管理,用 DNS challenge 自动签证书。 + +--- + +## 域名规划 + +所有域名 A 记录统一指向 `58.87.87.208`: + +| 域名 | 用途 | +|---|---| +| `hyonglin.top` | 主页(导航)+ SSH/RDP 直连(纯 DNS 不经 Caddy) | +| `www.hyonglin.top` | 301 重定向到 hyonglin.top | +| `note.hyonglin.top` | 笔记 Silverbullet | +| `frp.hyonglin.top` | frp 管理面板 | +| `ssh.hyonglin.top` | 网页 SSH 终端 | +| `git.hyonglin.top` | Git 服务(Gitea) | + +--- + +## 主页 + +静态页 `silverbullet/homepage/index.html`,导航分「自建服务」「常用链接」两组;以后加服务在 `