ccg-ros2-workflow 2.2.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -96
- package/README.zh-CN.md +256 -0
- package/dist/cli.mjs +15 -15
- package/dist/index.d.mts +59 -36
- package/dist/index.d.ts +59 -36
- package/dist/index.mjs +4 -4
- package/dist/shared/ccg-ros2-workflow.Bhm8c7P1.mjs +5154 -0
- package/package.json +31 -12
- package/templates/codex/AGENTS.md +348 -0
- package/templates/codex/agents/ccg-implement.toml +73 -0
- package/templates/codex/agents/ccg-research.toml +73 -0
- package/templates/codex/agents/ccg-review.toml +82 -0
- package/templates/codex/config.toml +21 -0
- package/templates/codex/hooks/ccg-workflow.py +253 -0
- package/templates/codex/hooks.json +15 -0
- package/templates/commands/agents/planner.md +97 -122
- package/templates/commands/agents/system-integrator.md +2 -2
- package/templates/commands/agents/team-architect.md +97 -0
- package/templates/commands/agents/team-qa.md +121 -0
- package/templates/commands/agents/team-reviewer.md +112 -0
- package/templates/commands/commit.md +30 -1
- package/templates/commands/context.md +332 -0
- package/templates/commands/go.md +206 -0
- package/templates/commands/init.md +1 -1
- package/templates/commands/spec-impl.md +41 -21
- package/templates/commands/spec-init.md +21 -27
- package/templates/commands/spec-plan.md +54 -21
- package/templates/commands/spec-research.md +78 -26
- package/templates/commands/spec-review.md +20 -16
- package/templates/{commands → commands-legacy}/analyze.md +1 -1
- package/templates/commands-legacy/backend.md +224 -0
- package/templates/commands-legacy/codex-exec.md +411 -0
- package/templates/{commands → commands-legacy}/debug.md +1 -1
- package/templates/commands-legacy/enhance.md +55 -0
- package/templates/{commands → commands-legacy}/feat.md +2 -2
- package/templates/commands-legacy/frontend.md +213 -0
- package/templates/{commands → commands-legacy}/optimize.md +1 -1
- package/templates/{commands → commands-legacy}/plan.md +1 -15
- package/templates/{commands → commands-legacy}/team-plan.md +1 -1
- package/templates/commands-legacy/team.md +475 -0
- package/templates/{commands → commands-legacy}/test.md +1 -1
- package/templates/commands-legacy/workflow.md +283 -0
- package/templates/engine/model-router.md +123 -0
- package/templates/engine/phase-guide.md +207 -0
- package/templates/engine/strategies/debug-investigate.md +169 -0
- package/templates/engine/strategies/deep-research.md +141 -0
- package/templates/engine/strategies/direct-fix.md +108 -0
- package/templates/engine/strategies/full-collaborate.md +389 -0
- package/templates/engine/strategies/git-action.md +43 -0
- package/templates/engine/strategies/guided-develop.md +282 -0
- package/templates/engine/strategies/optimize-measure.md +103 -0
- package/templates/engine/strategies/quick-implement.md +96 -0
- package/templates/engine/strategies/refactor-safely.md +180 -0
- package/templates/engine/strategies/review-audit.md +123 -0
- package/templates/hooks/session-start.js +100 -0
- package/templates/hooks/skill-router.js +144 -0
- package/templates/hooks/subagent-context.js +161 -0
- package/templates/hooks/task-utils.js +190 -0
- package/templates/hooks/workflow-state.js +55 -0
- package/templates/output-styles/abyss-command.md +56 -0
- package/templates/output-styles/abyss-concise.md +89 -0
- package/templates/output-styles/abyss-ritual.md +70 -0
- package/templates/output-styles/engineer-professional.md +20 -3
- package/templates/output-styles/laowang-engineer.md +2 -2
- package/templates/prompts/antigravity/analyzer.md +59 -0
- package/templates/prompts/antigravity/architect.md +55 -0
- package/templates/prompts/antigravity/builder.md +52 -0
- package/templates/prompts/antigravity/debugger.md +48 -0
- package/templates/prompts/antigravity/frontend.md +50 -0
- package/templates/prompts/antigravity/optimizer.md +40 -0
- package/templates/prompts/antigravity/reviewer.md +67 -0
- package/templates/prompts/antigravity/tester.md +39 -0
- package/templates/prompts/claude/debugger.md +1 -1
- package/templates/prompts/claude/reviewer.md +1 -1
- package/templates/prompts/codex/analyzer.md +8 -0
- package/templates/prompts/codex/architect.md +9 -1
- package/templates/prompts/codex/builder.md +61 -0
- package/templates/prompts/codex/debugger.md +9 -1
- package/templates/prompts/codex/optimizer.md +7 -0
- package/templates/prompts/codex/reviewer.md +7 -0
- package/templates/prompts/codex/tester.md +8 -1
- package/templates/prompts/gemini/analyzer.md +11 -3
- package/templates/prompts/gemini/architect.md +10 -2
- package/templates/prompts/gemini/debugger.md +8 -0
- package/templates/prompts/gemini/frontend.md +10 -2
- package/templates/prompts/gemini/optimizer.md +9 -2
- package/templates/prompts/gemini/reviewer.md +7 -0
- package/templates/prompts/gemini/tester.md +8 -1
- package/templates/rules/ccg-skill-routing.md +91 -0
- package/templates/rules/ccg-skills.md +65 -0
- package/templates/skills/SKILL.md +92 -0
- package/templates/skills/domains/ai/SKILL.md +34 -0
- package/templates/skills/domains/ai/agent-dev.md +242 -0
- package/templates/skills/domains/ai/llm-security.md +288 -0
- package/templates/skills/domains/ai/prompt-and-eval.md +279 -0
- package/templates/skills/domains/ai/rag-system.md +542 -0
- package/templates/skills/domains/architecture/SKILL.md +42 -0
- package/templates/skills/domains/architecture/api-design.md +225 -0
- package/templates/skills/domains/architecture/caching.md +299 -0
- package/templates/skills/domains/architecture/cloud-native.md +285 -0
- package/templates/skills/domains/architecture/message-queue.md +329 -0
- package/templates/skills/domains/architecture/security-arch.md +297 -0
- package/templates/skills/domains/data-engineering/SKILL.md +207 -0
- package/templates/skills/domains/development/SKILL.md +46 -0
- package/templates/skills/domains/development/cpp.md +369 -0
- package/templates/skills/domains/development/go.md +323 -0
- package/templates/skills/domains/development/java.md +277 -0
- package/templates/skills/domains/development/python.md +487 -0
- package/templates/skills/domains/development/rust.md +313 -0
- package/templates/skills/domains/development/shell.md +313 -0
- package/templates/skills/domains/development/typescript.md +277 -0
- package/templates/skills/domains/devops/SKILL.md +39 -0
- package/templates/skills/domains/devops/cost-optimization.md +272 -0
- package/templates/skills/domains/devops/database.md +217 -0
- package/templates/skills/domains/devops/devsecops.md +198 -0
- package/templates/skills/domains/devops/git-workflow.md +181 -0
- package/templates/skills/domains/devops/observability.md +280 -0
- package/templates/skills/domains/devops/performance.md +336 -0
- package/templates/skills/domains/devops/testing.md +283 -0
- package/templates/skills/domains/infrastructure/SKILL.md +200 -0
- package/templates/skills/domains/mobile/SKILL.md +224 -0
- package/templates/skills/domains/orchestration/SKILL.md +29 -0
- package/templates/skills/domains/orchestration/multi-agent.md +263 -0
- package/templates/skills/domains/ros2-control/SKILL.md +206 -0
- package/templates/skills/domains/ros2-hardware/SKILL.md +277 -0
- package/templates/skills/domains/ros2-manipulation/SKILL.md +237 -0
- package/templates/skills/domains/ros2-navigation/SKILL.md +196 -0
- package/templates/skills/domains/ros2-perception/SKILL.md +166 -0
- package/templates/skills/domains/ros2-upper-app/SKILL.md +50 -0
- package/templates/skills/domains/ros2-upper-app/launch-files.md +224 -0
- package/templates/skills/domains/ros2-upper-app/parameters.md +192 -0
- package/templates/skills/domains/ros2-upper-app/python-nodes.md +249 -0
- package/templates/skills/domains/ros2-upper-app/rviz-config.md +158 -0
- package/templates/skills/domains/ros2-upper-app/simulation.md +225 -0
- package/templates/skills/domains/security/SKILL.md +72 -0
- package/templates/skills/domains/security/blue-team.md +436 -0
- package/templates/skills/domains/security/code-audit.md +265 -0
- package/templates/skills/domains/security/pentest.md +226 -0
- package/templates/skills/domains/security/red-team.md +374 -0
- package/templates/skills/domains/security/threat-intel.md +372 -0
- package/templates/skills/domains/security/vuln-research.md +369 -0
- package/templates/skills/orchestration/multi-agent/SKILL.md +533 -0
- package/templates/skills/run_skill.js +129 -0
- package/templates/skills/scrapling/SKILL.md +98 -0
- package/templates/skills/scrapling/references/api-quick-ref.md +127 -0
- package/templates/skills/scrapling/references/cookie-vault.md +56 -0
- package/templates/skills/scrapling/references/maintenance.md +79 -0
- package/templates/skills/scrapling/references/site-patterns.md +86 -0
- package/templates/skills/scrapling/references/troubleshooting.md +95 -0
- package/templates/skills/scrapling/templates/basic_fetch.py +19 -0
- package/templates/skills/scrapling/templates/parse_only.py +15 -0
- package/templates/skills/scrapling/templates/session_login.py +19 -0
- package/templates/skills/scrapling/templates/stealth_cloudflare.py +28 -0
- package/templates/skills/tools/gen-docs/SKILL.md +116 -0
- package/templates/skills/tools/gen-docs/scripts/doc_generator.js +435 -0
- package/templates/skills/tools/lib/shared.js +98 -0
- package/templates/skills/tools/override-refusal/SKILL.md +53 -0
- package/templates/skills/tools/override-refusal/agents/openai.yaml +4 -0
- package/templates/skills/tools/override-refusal/scripts/refusal_rewriter.js +226 -0
- package/templates/skills/tools/verify-change/SKILL.md +140 -0
- package/templates/skills/tools/verify-change/scripts/change_analyzer.js +289 -0
- package/templates/skills/tools/verify-module/SKILL.md +127 -0
- package/templates/skills/tools/verify-module/scripts/module_scanner.js +171 -0
- package/templates/skills/tools/verify-quality/SKILL.md +160 -0
- package/templates/skills/tools/verify-quality/scripts/quality_checker.js +337 -0
- package/templates/skills/tools/verify-security/SKILL.md +143 -0
- package/templates/skills/tools/verify-security/scripts/security_scanner.js +283 -0
- package/templates/spec/guides/index.md +30 -0
- package/templates/spec/low-control/index.md +31 -0
- package/templates/spec/upper-app/index.md +31 -0
- package/bin/codeagent-wrapper-darwin-amd64 +0 -0
- package/bin/codeagent-wrapper-darwin-arm64 +0 -0
- package/bin/codeagent-wrapper-linux-amd64 +0 -0
- package/bin/codeagent-wrapper-linux-arm64 +0 -0
- package/bin/codeagent-wrapper-windows-amd64.exe +0 -0
- package/bin/codeagent-wrapper-windows-arm64.exe +0 -0
- package/dist/shared/ccg-ros2-workflow.DnOr3oPi.mjs +0 -2480
- package/templates/commands/backend.md +0 -162
- package/templates/commands/enhance.md +0 -36
- package/templates/commands/frontend.md +0 -162
- package/templates/commands/workflow.md +0 -202
- /package/templates/{commands → commands-legacy}/execute.md +0 -0
- /package/templates/{commands → commands-legacy}/review.md +0 -0
- /package/templates/{commands → commands-legacy}/team-exec.md +0 -0
- /package/templates/{commands → commands-legacy}/team-research.md +0 -0
- /package/templates/{commands → commands-legacy}/team-review.md +0 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ros2-perception
|
|
3
|
+
description: ROS2 感知技能。激光雷达、相机、点云处理、传感器融合、SLAM 输入。当用户提到激光雷达、LiDAR、点云、PCL、PointCloud2、相机标定、深度图、传感器融合时使用。
|
|
4
|
+
user-invocable: false
|
|
5
|
+
category: domain
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# ROS2 感知技能
|
|
9
|
+
|
|
10
|
+
## 适用场景
|
|
11
|
+
|
|
12
|
+
机器人感知层开发,处理传感器原始数据并提取语义信息。
|
|
13
|
+
|
|
14
|
+
### 触发关键词
|
|
15
|
+
|
|
16
|
+
- 激光雷达 / LiDAR / RPLidar / Velodyne / Ouster
|
|
17
|
+
- 点云 / PointCloud2 / PCL / 点云分割 / 体素
|
|
18
|
+
- 相机 / RGB / 深度相机 / RealSense / ZED
|
|
19
|
+
- 标定 / calibration / 内参 / 外参
|
|
20
|
+
- SLAM 输入 / 里程计输入 / 传感器融合
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 激光雷达驱动
|
|
25
|
+
|
|
26
|
+
### 标准包列表
|
|
27
|
+
|
|
28
|
+
| 厂商 | ROS2 包 | 默认 Topic |
|
|
29
|
+
|------|---------|------------|
|
|
30
|
+
| RPLidar | `rplidar_ros` | `/scan` (sensor_msgs/LaserScan) |
|
|
31
|
+
| Velodyne | `velodyne_driver` | `/velodyne_points` (sensor_msgs/PointCloud2) |
|
|
32
|
+
| Ouster | `ouster_ros` | `/ouster/points` |
|
|
33
|
+
| Livox | `livox_ros_driver2` | `/livox/lidar` |
|
|
34
|
+
|
|
35
|
+
### 启动示例
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
# launch/rplidar.launch.py
|
|
39
|
+
Node(
|
|
40
|
+
package='rplidar_ros',
|
|
41
|
+
executable='rplidar_node',
|
|
42
|
+
name='rplidar',
|
|
43
|
+
parameters=[{
|
|
44
|
+
'serial_port': '/dev/ttyUSB0',
|
|
45
|
+
'frame_id': 'laser_link',
|
|
46
|
+
'angle_compensate': True,
|
|
47
|
+
'scan_mode': 'Standard',
|
|
48
|
+
}],
|
|
49
|
+
)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 点云处理 (PCL)
|
|
55
|
+
|
|
56
|
+
### 体素降采样
|
|
57
|
+
|
|
58
|
+
```cpp
|
|
59
|
+
#include <pcl/filters/voxel_grid.h>
|
|
60
|
+
#include <pcl_conversions/pcl_conversions.h>
|
|
61
|
+
|
|
62
|
+
void cloud_callback(const sensor_msgs::msg::PointCloud2::SharedPtr msg) {
|
|
63
|
+
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
|
|
64
|
+
pcl::fromROSMsg(*msg, *cloud);
|
|
65
|
+
|
|
66
|
+
pcl::VoxelGrid<pcl::PointXYZ> voxel;
|
|
67
|
+
voxel.setInputCloud(cloud);
|
|
68
|
+
voxel.setLeafSize(0.05f, 0.05f, 0.05f); // 5cm 体素
|
|
69
|
+
pcl::PointCloud<pcl::PointXYZ>::Ptr filtered(new pcl::PointCloud<pcl::PointXYZ>);
|
|
70
|
+
voxel.filter(*filtered);
|
|
71
|
+
|
|
72
|
+
sensor_msgs::msg::PointCloud2 output;
|
|
73
|
+
pcl::toROSMsg(*filtered, output);
|
|
74
|
+
output.header = msg->header;
|
|
75
|
+
pub_->publish(output);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 平面分割 (RANSAC)
|
|
80
|
+
|
|
81
|
+
```cpp
|
|
82
|
+
#include <pcl/segmentation/sac_segmentation.h>
|
|
83
|
+
|
|
84
|
+
pcl::SACSegmentation<pcl::PointXYZ> seg;
|
|
85
|
+
seg.setOptimizeCoefficients(true);
|
|
86
|
+
seg.setModelType(pcl::SACMODEL_PLANE);
|
|
87
|
+
seg.setMethodType(pcl::SAC_RANSAC);
|
|
88
|
+
seg.setDistanceThreshold(0.01);
|
|
89
|
+
seg.setInputCloud(cloud);
|
|
90
|
+
|
|
91
|
+
pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
|
|
92
|
+
pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
|
|
93
|
+
seg.segment(*inliers, *coefficients);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 相机集成
|
|
99
|
+
|
|
100
|
+
### RealSense 启动
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
ros2 launch realsense2_camera rs_launch.py \
|
|
104
|
+
enable_color:=true \
|
|
105
|
+
enable_depth:=true \
|
|
106
|
+
align_depth.enable:=true \
|
|
107
|
+
pointcloud.enable:=true
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 深度图转点云
|
|
111
|
+
|
|
112
|
+
```cpp
|
|
113
|
+
// depth_image_proc 功能包提供
|
|
114
|
+
#include <depth_image_proc/point_cloud_xyz.hpp>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 传感器融合
|
|
120
|
+
|
|
121
|
+
### TF2 时间同步
|
|
122
|
+
|
|
123
|
+
```cpp
|
|
124
|
+
#include <message_filters/subscriber.h>
|
|
125
|
+
#include <message_filters/time_synchronizer.h>
|
|
126
|
+
#include <message_filters/sync_policies/approximate_time.h>
|
|
127
|
+
|
|
128
|
+
using SyncPolicy = message_filters::sync_policies::ApproximateTime<
|
|
129
|
+
sensor_msgs::msg::PointCloud2,
|
|
130
|
+
sensor_msgs::msg::Image>;
|
|
131
|
+
|
|
132
|
+
message_filters::Subscriber<sensor_msgs::msg::PointCloud2> cloud_sub_;
|
|
133
|
+
message_filters::Subscriber<sensor_msgs::msg::Image> image_sub_;
|
|
134
|
+
message_filters::Synchronizer<SyncPolicy> sync_(SyncPolicy(10), cloud_sub_, image_sub_);
|
|
135
|
+
sync_.registerCallback(&Node::fusion_callback, this);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 关键 QoS 策略
|
|
141
|
+
|
|
142
|
+
| 数据类型 | Reliability | Durability | History | Depth |
|
|
143
|
+
|----------|-------------|------------|---------|-------|
|
|
144
|
+
| LaserScan | Best Effort | Volatile | Keep Last | 5 |
|
|
145
|
+
| PointCloud2 | Best Effort | Volatile | Keep Last | 1 |
|
|
146
|
+
| Image (高分辨率) | Best Effort | Volatile | Keep Last | 1 |
|
|
147
|
+
| 相机内参 | Reliable | Transient Local | Keep Last | 1 |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 调试工具
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# 查看话题数据
|
|
155
|
+
ros2 topic echo /scan --no-arr
|
|
156
|
+
ros2 topic hz /velodyne_points
|
|
157
|
+
|
|
158
|
+
# RViz2 可视化
|
|
159
|
+
rviz2 -d perception.rviz
|
|
160
|
+
|
|
161
|
+
# 录制 rosbag
|
|
162
|
+
ros2 bag record /scan /velodyne_points /camera/image_raw
|
|
163
|
+
|
|
164
|
+
# 回放
|
|
165
|
+
ros2 bag play <bag_file>
|
|
166
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ros2-upper-app
|
|
3
|
+
description: ROS2 上层应用集成域。Launch 编排、参数配置、RViz 可视化、Python 节点、Gazebo/Ignition 仿真。当用户提到 launch 文件、launch.py、参数 YAML、RViz、URDF 显示、Python 节点、rclpy、Gazebo、Ignition 仿真、机器人状态发布时使用。
|
|
4
|
+
user-invocable: false
|
|
5
|
+
category: domain
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# ROS2 上层应用集成域
|
|
9
|
+
|
|
10
|
+
## 域定位
|
|
11
|
+
|
|
12
|
+
负责 ROS2 系统的**上层编排与可视化**——把各个底层节点(感知/控制/驱动)串成可启动、可配置、可视化、可仿真的整体。
|
|
13
|
+
|
|
14
|
+
**Authority Model**: Antigravity 优先(默认),Gemini 备选。
|
|
15
|
+
|
|
16
|
+
## 子技能索引
|
|
17
|
+
|
|
18
|
+
| 子技能 | 职责 | 触发关键词 |
|
|
19
|
+
|--------|------|------------|
|
|
20
|
+
| [launch-files.md](./launch-files.md) | Launch 文件编排 | launch, launch.py, IncludeLaunchDescription, launch_arguments |
|
|
21
|
+
| [parameters.md](./parameters.md) | 参数 YAML / declare_parameter | params.yaml, ros__parameters, declare_parameter, override |
|
|
22
|
+
| [rviz-config.md](./rviz-config.md) | RViz 可视化配置 | rviz, rviz2, .rviz config, displays, fixed frame, TF tree |
|
|
23
|
+
| [python-nodes.md](./python-nodes.md) | rclpy 节点开发 | rclpy, Python node, async, MultiThreadedExecutor, callback group |
|
|
24
|
+
| [simulation.md](./simulation.md) | Gazebo / Ignition 仿真 | gazebo, gz, ignition, sdf, world, robot_state_publisher, controller spawner |
|
|
25
|
+
|
|
26
|
+
## 与其他 ROS2 域的关系
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
┌─────────────────────────────┐
|
|
30
|
+
│ ros2-upper-app(本域) │ ← Antigravity 主导
|
|
31
|
+
│ Launch / Params / Viz │
|
|
32
|
+
└──────────┬──────────────────┘
|
|
33
|
+
│ 启动并连接
|
|
34
|
+
↓
|
|
35
|
+
┌──────────────────────────────────────────────┐
|
|
36
|
+
│ ros2-perception / control / navigation / │ ← Codex 主导
|
|
37
|
+
│ manipulation / hardware │
|
|
38
|
+
└──────────────────────────────────────────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- 本域负责 **how to compose**(如何组装)
|
|
42
|
+
- 其他 ROS2 域负责 **what to compute**(算什么)
|
|
43
|
+
|
|
44
|
+
## 通用约束
|
|
45
|
+
|
|
46
|
+
- 路径不要硬编码 — 用 `FindPackageShare` + `PathJoinSubstitution`
|
|
47
|
+
- 参数不要散落在 launch 中 — 集中到 `config/*.yaml`
|
|
48
|
+
- 节点命名空间显式声明 — 多机器人场景下避免冲突
|
|
49
|
+
- TF tree 单根原则 — 全系统只有一个根 frame(通常是 `map` 或 `odom`)
|
|
50
|
+
- `use_sim_time` 在仿真场景必须显式传递到所有节点
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# ROS2 Launch 文件编排
|
|
2
|
+
|
|
3
|
+
## 何时使用
|
|
4
|
+
|
|
5
|
+
- 启动单节点(`Node`)
|
|
6
|
+
- 多节点编排,带启动顺序、条件、重映射
|
|
7
|
+
- 复用其他 launch 文件(`IncludeLaunchDescription`)
|
|
8
|
+
- 接收命令行参数 / 从 YAML 读取参数
|
|
9
|
+
|
|
10
|
+
## 标准 launch.py 模板
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
from launch import LaunchDescription
|
|
14
|
+
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription, GroupAction
|
|
15
|
+
from launch.conditions import IfCondition, UnlessCondition
|
|
16
|
+
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
|
17
|
+
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution, TextSubstitution
|
|
18
|
+
from launch_ros.actions import Node, PushRosNamespace
|
|
19
|
+
from launch_ros.substitutions import FindPackageShare
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def generate_launch_description():
|
|
23
|
+
pkg_share = FindPackageShare('my_robot')
|
|
24
|
+
|
|
25
|
+
use_sim_time = LaunchConfiguration('use_sim_time')
|
|
26
|
+
namespace = LaunchConfiguration('namespace')
|
|
27
|
+
params_file = LaunchConfiguration('params_file')
|
|
28
|
+
|
|
29
|
+
declare_use_sim_time = DeclareLaunchArgument(
|
|
30
|
+
'use_sim_time', default_value='false',
|
|
31
|
+
description='Use simulation (Gazebo) clock if true')
|
|
32
|
+
|
|
33
|
+
declare_namespace = DeclareLaunchArgument(
|
|
34
|
+
'namespace', default_value='',
|
|
35
|
+
description='Top-level namespace')
|
|
36
|
+
|
|
37
|
+
declare_params = DeclareLaunchArgument(
|
|
38
|
+
'params_file',
|
|
39
|
+
default_value=PathJoinSubstitution([pkg_share, 'config', 'params.yaml']),
|
|
40
|
+
description='Full path to the ROS2 parameters file')
|
|
41
|
+
|
|
42
|
+
bringup_group = GroupAction([
|
|
43
|
+
PushRosNamespace(namespace),
|
|
44
|
+
|
|
45
|
+
Node(
|
|
46
|
+
package='my_robot',
|
|
47
|
+
executable='controller_node',
|
|
48
|
+
name='controller',
|
|
49
|
+
parameters=[params_file, {'use_sim_time': use_sim_time}],
|
|
50
|
+
remappings=[
|
|
51
|
+
('/cmd_vel', 'cmd_vel'),
|
|
52
|
+
('/odom', 'odom'),
|
|
53
|
+
],
|
|
54
|
+
output='screen',
|
|
55
|
+
emulate_tty=True,
|
|
56
|
+
),
|
|
57
|
+
|
|
58
|
+
IncludeLaunchDescription(
|
|
59
|
+
PythonLaunchDescriptionSource(
|
|
60
|
+
PathJoinSubstitution([pkg_share, 'launch', 'sensors.launch.py'])),
|
|
61
|
+
launch_arguments={
|
|
62
|
+
'use_sim_time': use_sim_time,
|
|
63
|
+
}.items(),
|
|
64
|
+
),
|
|
65
|
+
])
|
|
66
|
+
|
|
67
|
+
return LaunchDescription([
|
|
68
|
+
declare_use_sim_time,
|
|
69
|
+
declare_namespace,
|
|
70
|
+
declare_params,
|
|
71
|
+
bringup_group,
|
|
72
|
+
])
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 关键 API
|
|
76
|
+
|
|
77
|
+
### Node 参数
|
|
78
|
+
|
|
79
|
+
| 参数 | 用途 |
|
|
80
|
+
|------|------|
|
|
81
|
+
| `package` | ament 包名 |
|
|
82
|
+
| `executable` | `setup.py` 中 console_scripts 名,或 C++ 可执行文件名 |
|
|
83
|
+
| `name` | 节点运行时名(不写则用代码里的名) |
|
|
84
|
+
| `namespace` | 节点的 ROS namespace |
|
|
85
|
+
| `parameters` | 列表:dict / yaml 文件路径都可以 |
|
|
86
|
+
| `remappings` | `[(from, to), ...]` |
|
|
87
|
+
| `arguments` | 透传给 `argv` |
|
|
88
|
+
| `respawn` | 崩溃自动重启 |
|
|
89
|
+
| `output` | `screen`(打印到终端)/ `log`(写入日志) |
|
|
90
|
+
| `emulate_tty` | 让 RCLCPP_INFO 等日志保留颜色 |
|
|
91
|
+
|
|
92
|
+
### 路径替换(永远不要硬编码)
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
# ❌ 错误
|
|
96
|
+
params=['/opt/ros/humble/share/my_pkg/config/params.yaml']
|
|
97
|
+
|
|
98
|
+
# ✅ 正确
|
|
99
|
+
PathJoinSubstitution([
|
|
100
|
+
FindPackageShare('my_pkg'), 'config', 'params.yaml'
|
|
101
|
+
])
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## 条件启动
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from launch.conditions import IfCondition, UnlessCondition
|
|
108
|
+
|
|
109
|
+
Node(
|
|
110
|
+
package='rviz2', executable='rviz2',
|
|
111
|
+
condition=IfCondition(LaunchConfiguration('use_rviz')),
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# CLI: ros2 launch my_robot bringup.launch.py use_rviz:=true
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 启动顺序与延迟
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from launch.actions import TimerAction
|
|
121
|
+
from launch.event_handlers import OnProcessStart
|
|
122
|
+
from launch.actions import RegisterEventHandler
|
|
123
|
+
|
|
124
|
+
# 方案 A: 固定延时(简单但不优雅)
|
|
125
|
+
TimerAction(period=2.0, actions=[
|
|
126
|
+
Node(package='nav2_bringup', executable='bringup_launcher')
|
|
127
|
+
])
|
|
128
|
+
|
|
129
|
+
# 方案 B: 事件驱动(推荐)
|
|
130
|
+
RegisterEventHandler(
|
|
131
|
+
OnProcessStart(
|
|
132
|
+
target_action=robot_state_publisher_node,
|
|
133
|
+
on_start=[
|
|
134
|
+
Node(package='controller_manager', executable='spawner',
|
|
135
|
+
arguments=['joint_state_broadcaster'])
|
|
136
|
+
]
|
|
137
|
+
)
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## 包含其他 launch
|
|
142
|
+
|
|
143
|
+
### Python launch
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
IncludeLaunchDescription(
|
|
147
|
+
PythonLaunchDescriptionSource(
|
|
148
|
+
PathJoinSubstitution([FindPackageShare('nav2_bringup'),
|
|
149
|
+
'launch', 'bringup_launch.py'])),
|
|
150
|
+
launch_arguments={'use_sim_time': 'true'}.items(),
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### XML launch(老式)
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from launch.launch_description_sources import FrontendLaunchDescriptionSource
|
|
158
|
+
|
|
159
|
+
IncludeLaunchDescription(
|
|
160
|
+
FrontendLaunchDescriptionSource(
|
|
161
|
+
PathJoinSubstitution([FindPackageShare('legacy_pkg'),
|
|
162
|
+
'launch', 'old.launch.xml']))
|
|
163
|
+
)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## 多机器人 / 命名空间
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
robots = [
|
|
170
|
+
{'name': 'robot1', 'x': '0', 'y': '0'},
|
|
171
|
+
{'name': 'robot2', 'x': '2', 'y': '0'},
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
actions = []
|
|
175
|
+
for r in robots:
|
|
176
|
+
actions.append(GroupAction([
|
|
177
|
+
PushRosNamespace(r['name']),
|
|
178
|
+
Node(package='my_robot', executable='controller', name='controller'),
|
|
179
|
+
]))
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## install 配置(否则 launch 找不到)
|
|
183
|
+
|
|
184
|
+
`CMakeLists.txt`(ament_cmake 包):
|
|
185
|
+
```cmake
|
|
186
|
+
install(DIRECTORY launch config rviz urdf
|
|
187
|
+
DESTINATION share/${PROJECT_NAME})
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`setup.py`(ament_python 包):
|
|
191
|
+
```python
|
|
192
|
+
data_files=[
|
|
193
|
+
('share/' + package_name, ['package.xml']),
|
|
194
|
+
(os.path.join('share', package_name, 'launch'),
|
|
195
|
+
glob('launch/*.launch.py')),
|
|
196
|
+
(os.path.join('share', package_name, 'config'),
|
|
197
|
+
glob('config/*.yaml')),
|
|
198
|
+
],
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## 调试
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# 列出所有可用 launch
|
|
205
|
+
ros2 pkg list | xargs -I{} ros2 launch --show-args {} 2>/dev/null
|
|
206
|
+
|
|
207
|
+
# 看 launch 实际展开成什么节点
|
|
208
|
+
ros2 launch my_robot bringup.launch.py --show-args
|
|
209
|
+
|
|
210
|
+
# 启动后查看节点拓扑
|
|
211
|
+
ros2 node list
|
|
212
|
+
ros2 node info /controller
|
|
213
|
+
ros2 topic list -t
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## 常见反模式
|
|
217
|
+
|
|
218
|
+
| 反模式 | 问题 | 修复 |
|
|
219
|
+
|--------|------|------|
|
|
220
|
+
| 路径硬编码 | 装载到其他机器或 colcon 构建后失效 | `FindPackageShare` |
|
|
221
|
+
| 参数散落 launch 各处 | 难以从外部覆盖,难审计 | 集中到 `config/*.yaml` |
|
|
222
|
+
| 节点重启策略缺失 | 单节点崩溃整个系统挂 | `respawn=True` + 上限 |
|
|
223
|
+
| `use_sim_time` 不传递 | 仿真时间不一致,TF 错乱 | 顶层 LaunchConfiguration 透传到所有 Node |
|
|
224
|
+
| 多 launch 重复 declare 同名参数 | 后者覆盖前者,行为难以预测 | 顶层 declare,子 launch 通过 launch_arguments 接收 |
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# ROS2 参数体系
|
|
2
|
+
|
|
3
|
+
## 参数三层模型
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
[CLI / launch override] 最高优先级
|
|
7
|
+
↓
|
|
8
|
+
[YAML params_file] 中等
|
|
9
|
+
↓
|
|
10
|
+
[declare_parameter 默认值] 最低
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## YAML 标准格式
|
|
14
|
+
|
|
15
|
+
### 节点完整名(/ namespace + 节点名)
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
# config/params.yaml
|
|
19
|
+
controller:
|
|
20
|
+
ros__parameters:
|
|
21
|
+
max_speed: 1.0
|
|
22
|
+
safe_distance: 0.5
|
|
23
|
+
enabled_features:
|
|
24
|
+
- lidar
|
|
25
|
+
- imu
|
|
26
|
+
|
|
27
|
+
/robot1/controller:
|
|
28
|
+
ros__parameters:
|
|
29
|
+
max_speed: 0.8
|
|
30
|
+
|
|
31
|
+
# 通配符(rclcpp_components / 多节点共享)
|
|
32
|
+
"/**":
|
|
33
|
+
ros__parameters:
|
|
34
|
+
use_sim_time: false
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 嵌套参数(reflected as dotted keys)
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
controller:
|
|
41
|
+
ros__parameters:
|
|
42
|
+
pid:
|
|
43
|
+
kp: 1.0
|
|
44
|
+
ki: 0.1
|
|
45
|
+
kd: 0.01
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
代码中读:`this->get_parameter("pid.kp")`
|
|
49
|
+
|
|
50
|
+
## 节点端声明
|
|
51
|
+
|
|
52
|
+
### C++
|
|
53
|
+
|
|
54
|
+
```cpp
|
|
55
|
+
class Controller : public rclcpp::Node {
|
|
56
|
+
public:
|
|
57
|
+
Controller() : Node("controller") {
|
|
58
|
+
this->declare_parameter<double>("max_speed", 1.0);
|
|
59
|
+
this->declare_parameter<double>("safe_distance", 0.5);
|
|
60
|
+
this->declare_parameter<std::vector<std::string>>("enabled_features", {});
|
|
61
|
+
|
|
62
|
+
max_speed_ = this->get_parameter("max_speed").as_double();
|
|
63
|
+
enabled_ = this->get_parameter("enabled_features").as_string_array();
|
|
64
|
+
|
|
65
|
+
// 监听运行时变化
|
|
66
|
+
param_cb_handle_ = this->add_on_set_parameters_callback(
|
|
67
|
+
[this](const std::vector<rclcpp::Parameter>& params) {
|
|
68
|
+
rcl_interfaces::msg::SetParametersResult result;
|
|
69
|
+
result.successful = true;
|
|
70
|
+
for (const auto& p : params) {
|
|
71
|
+
if (p.get_name() == "max_speed") {
|
|
72
|
+
if (p.as_double() < 0) {
|
|
73
|
+
result.successful = false;
|
|
74
|
+
result.reason = "max_speed must be >= 0";
|
|
75
|
+
} else {
|
|
76
|
+
max_speed_ = p.as_double();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private:
|
|
85
|
+
double max_speed_;
|
|
86
|
+
std::vector<std::string> enabled_;
|
|
87
|
+
OnSetParametersCallbackHandle::SharedPtr param_cb_handle_;
|
|
88
|
+
};
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Python
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from rcl_interfaces.msg import SetParametersResult
|
|
95
|
+
|
|
96
|
+
class Controller(Node):
|
|
97
|
+
def __init__(self):
|
|
98
|
+
super().__init__('controller')
|
|
99
|
+
|
|
100
|
+
self.declare_parameter('max_speed', 1.0)
|
|
101
|
+
self.declare_parameter('safe_distance', 0.5)
|
|
102
|
+
self.declare_parameter('enabled_features', [])
|
|
103
|
+
|
|
104
|
+
self.max_speed = self.get_parameter('max_speed').value
|
|
105
|
+
|
|
106
|
+
self.add_on_set_parameters_callback(self.on_param_change)
|
|
107
|
+
|
|
108
|
+
def on_param_change(self, params):
|
|
109
|
+
for p in params:
|
|
110
|
+
if p.name == 'max_speed':
|
|
111
|
+
if p.value < 0:
|
|
112
|
+
return SetParametersResult(
|
|
113
|
+
successful=False, reason='must be >= 0')
|
|
114
|
+
self.max_speed = p.value
|
|
115
|
+
return SetParametersResult(successful=True)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## 参数描述符(强约束 + 文档化)
|
|
119
|
+
|
|
120
|
+
```cpp
|
|
121
|
+
auto descriptor = rcl_interfaces::msg::ParameterDescriptor();
|
|
122
|
+
descriptor.description = "Maximum linear speed in m/s";
|
|
123
|
+
|
|
124
|
+
rcl_interfaces::msg::FloatingPointRange range;
|
|
125
|
+
range.from_value = 0.0;
|
|
126
|
+
range.to_value = 5.0;
|
|
127
|
+
descriptor.floating_point_range.push_back(range);
|
|
128
|
+
|
|
129
|
+
this->declare_parameter("max_speed", 1.0, descriptor);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
效果:`ros2 param set` 超出 [0, 5] 直接拒绝。
|
|
133
|
+
|
|
134
|
+
## CLI 操作
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# 列出节点参数
|
|
138
|
+
ros2 param list /controller
|
|
139
|
+
|
|
140
|
+
# 读
|
|
141
|
+
ros2 param get /controller max_speed
|
|
142
|
+
|
|
143
|
+
# 写
|
|
144
|
+
ros2 param set /controller max_speed 0.8
|
|
145
|
+
|
|
146
|
+
# 整体 dump
|
|
147
|
+
ros2 param dump /controller > current.yaml
|
|
148
|
+
|
|
149
|
+
# 整体 load
|
|
150
|
+
ros2 param load /controller params.yaml
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 在 Launch 中加载
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
Node(
|
|
157
|
+
package='my_robot',
|
|
158
|
+
executable='controller_node',
|
|
159
|
+
name='controller',
|
|
160
|
+
parameters=[
|
|
161
|
+
# 1. 来自 YAML
|
|
162
|
+
PathJoinSubstitution([FindPackageShare('my_robot'),
|
|
163
|
+
'config', 'params.yaml']),
|
|
164
|
+
# 2. 命令行覆盖单项
|
|
165
|
+
{'max_speed': LaunchConfiguration('max_speed')},
|
|
166
|
+
# 3. 强制 use_sim_time
|
|
167
|
+
{'use_sim_time': use_sim_time},
|
|
168
|
+
],
|
|
169
|
+
)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
注意:**列表后面的覆盖前面的**。
|
|
173
|
+
|
|
174
|
+
## 命名约定
|
|
175
|
+
|
|
176
|
+
| 类型 | 风格 |
|
|
177
|
+
|------|------|
|
|
178
|
+
| 简单标量 | `snake_case`: `max_speed` |
|
|
179
|
+
| 嵌套组 | `pid.kp`, `pid.ki` |
|
|
180
|
+
| 频率 | `update_rate_hz` (单位写在名里) |
|
|
181
|
+
| 启用开关 | `enable_<feature>` 或 `<feature>.enabled` |
|
|
182
|
+
| 阈值 | `min_<x>` / `max_<x>` / `<x>_threshold` |
|
|
183
|
+
|
|
184
|
+
## 反模式
|
|
185
|
+
|
|
186
|
+
| 反模式 | 后果 |
|
|
187
|
+
|--------|------|
|
|
188
|
+
| 不 declare 直接 get | 抛 `ParameterNotDeclaredException` |
|
|
189
|
+
| 在构造函数读完就忘了 | 运行时改参数无效 — 用 set 回调 |
|
|
190
|
+
| 不同节点参数命名风格混乱 | 难维护、难审计 |
|
|
191
|
+
| 把硬件路径写死(`/dev/ttyUSB0`) | udev 编号变化即崩 — 改成参数 + udev rules |
|
|
192
|
+
| 把超大数据(图像、点云)塞参数 | 参数服务器不是为大数据设计的 — 用 topic |
|