first commit

This commit is contained in:
2026-07-22 13:48:46 +08:00
commit c87751c3dc
2820 changed files with 726976 additions and 0 deletions
@@ -0,0 +1,55 @@
# SRDF disabled collisions
Disabled collisions are planning-safety data. Treat them as derived evidence, not as decorative XML.
## Valid sources
Use one of these sources:
- adjacent-link policy from the URDF kinematic graph;
- MoveIt Setup Assistant self-collision matrix generation;
- sampled collision analysis from a known MoveIt configuration;
- explicit user-provided collision matrix;
- a manually reviewed pair with a specific rationale.
Do not infer disabled collision pairs from visual appearance or vague prose.
## XML shape
```xml
<disable_collisions link1="base_link" link2="shoulder_link" reason="Adjacent"/>
```
The current runtime requires:
- `link1` and `link2`;
- both links to exist in the URDF;
- distinct link names;
- a non-empty `reason`;
- no duplicate or reversed duplicate pairs.
## Reason and provenance
Use truthful reasons. Examples:
| Reason | Typical source |
|---|---|
| `Adjacent` | URDF graph adjacency |
| `Never` | Setup Assistant sampled matrix |
| `Always` | Setup Assistant sampled matrix |
| `Default` | Setup Assistant sampled matrix |
| `Manual: tool fixture is outside workspace envelope` | Explicit human review |
The current parser classifies reasons into broad provenance buckets such as adjacent, sampled, setup assistant, manual, or assumed. Avoid `assumed` unless the user explicitly requested a provisional SRDF and the risk is reported.
## Review checklist
Before committing a disabled collision pair:
- Is the pair adjacent or sampled-safe?
- Does disabling the pair hide a possible real collision during the planned task?
- Was the pair generated with sufficient sampling density?
- Is the pair still valid after geometry, limits, or group membership changed?
- Was manual rationale written down?
If many manual pairs are present, prefer regenerating the self-collision matrix with MoveIt Setup Assistant.
@@ -0,0 +1,73 @@
# SRDF end effectors
Use this reference when creating or editing `<end_effector>` entries or preparing MoveIt2 pose-target handoffs for `$cad-viewer`.
## Concept
An end effector is a semantic designation for a tool, gripper, sensor head, or other terminal group. It is typically connected to a parent planning group through a fixed joint or attachment link.
Typical shape:
```xml
<group name="gripper">
<joint name="finger_joint"/>
</group>
<end_effector
name="gripper_eef"
parent_link="tool0"
group="gripper"
parent_group="manipulator"/>
```
## Required ledger fields
Record:
- end-effector name;
- end-effector group;
- parent planning group;
- parent link where the end effector attaches;
- target/TCP link used for IK and planning;
- whether the end-effector group overlaps the parent group;
- whether the parent link is adjacent to the end-effector group in the URDF graph.
## Checks
Before generation:
- The end-effector group exists.
- The parent group exists when specified.
- The parent link exists in the URDF.
- The end-effector group and parent group do not share links.
- The parent link is in the parent group or adjacent to the end-effector group.
- The target/TCP link is explicit when it differs from the inferred group tip.
The current runtime enforces several of these checks, but target/TCP choice remains a semantic decision. Do not rely on inference when planning to a tool center point.
## CAD Viewer MoveIt2 target link
When handing an SRDF to `$cad-viewer` for optional MoveIt2 controls, make the intended target link explicit when possible:
```json
{
"protocolVersion": 1,
"type": "srdf.solvePose",
"payload": {
"file": "robot.srdf",
"target": {
"endEffector": "gripper_eef",
"targetLink": "tool0",
"frame": "base_link",
"xyz": [0.4, 0.0, 0.2],
"quat_xyzw": [0, 0, 0, 1]
},
"moveit2": {
"planningGroup": "manipulator",
"targetLink": "tool0"
}
}
}
```
Use position-only IK only when orientation is intentionally unconstrained. CAD Viewer owns the local MoveIt2 server startup and protocol details.
@@ -0,0 +1,34 @@
# SRDF generation command
Regenerate explicit MoveIt SRDF outputs from Python sources with top-level `gen_srdf()` functions.
```bash
python scripts/srdf path/to/semantic.py
python scripts/srdf path/to/semantic.py -o path/to/robot.srdf
python scripts/srdf path/to/a.py=out/a.srdf path/to/b.py=out/b.srdf
```
Plain Python targets write a sibling `.srdf` beside the source. `-o` / `--output` is valid only with one plain target. Use `SOURCE.py=OUTPUT.srdf` pairs for custom multi-target destinations.
`gen_srdf()` must return an envelope dictionary containing:
- `xml`: complete SRDF `<robot>` XML as an `xml.etree.ElementTree.Element` or XML string;
- `urdf`: a POSIX relative path from the generator source file to the linked `.urdf`.
## What the command does
The tool:
1. imports the target Python source;
2. calls `gen_srdf()`;
3. resolves the linked URDF path relative to the generator source file;
4. injects or updates local `tcad:urdf` metadata so downstream tools can find the URDF;
5. parses the generated SRDF;
6. validates the SRDF against the linked URDF;
7. writes the requested `.srdf` only after validation passes.
There is no hidden SRDF artifact. The generated `.srdf` is the MoveIt inventory handed to `$cad-viewer` for a live CAD Viewer link and optional MoveIt2 controls.
## Execution safety
The CLI imports generator modules directly. Top-level Python code in the generator file will execute. Use this command only for trusted project sources.
@@ -0,0 +1,126 @@
# SRDF generator contract
Define a top-level zero-argument `gen_srdf()` function in a Python source file. It must return an envelope dictionary with the root SRDF XML and the owning URDF path.
```python
import xml.etree.ElementTree as ET
def gen_srdf():
robot = ET.Element("robot", {"name": "sample_robot"})
group = ET.SubElement(robot, "group", {"name": "manipulator"})
ET.SubElement(group, "chain", {"base_link": "base_link", "tip_link": "tool0"})
return {
"xml": robot,
"urdf": "sample_robot.urdf",
}
```
## Required envelope
```python
{
"xml": robot_root_element_or_xml_string,
"urdf": "relative/path/to/robot.urdf",
}
```
The current runtime accepts only `xml` and `urdf` fields. Do not add unsupported fields.
## XML root
The XML root must be:
```xml
<robot name="...">
```
The SRDF `robot` name must match the linked URDF robot name.
## URDF path
The `urdf` field is resolved relative to the generator source file. It must:
- be a non-empty string;
- use POSIX `/` separators;
- be relative, not absolute;
- end in `.urdf`;
- refer to an existing file.
The CLI injects or updates:
```xml
<tcad:urdf path="..."/>
```
The `tcad` prefix is emitted with the `https://text-to-cad.dev/srdf` namespace. The injected path is relative from the generated `.srdf` location to the linked URDF. This metadata is a local SRDF convention for downstream tools; it is not a core SRDF semantic element. Readers also accept existing legacy `<explorer:urdf/>` metadata.
## Supported target forms
```bash
python scripts/srdf path/to/source.py
python scripts/srdf path/to/source.py -o path/to/robot.srdf
python scripts/srdf a.py=out/a.srdf b.py=out/b.srdf
```
The generated output path is selected by the CLI. The generator should not write the `.srdf` file itself.
## Group-state units
Group-state joint values are URDF-native values:
- revolute and continuous joints: radians;
- prismatic joints: meters.
Do not store degrees in SRDF. Legacy UI/protocol degree fields are compatibility aliases and must be converted by joint type.
## Example with common semantic elements
```python
import xml.etree.ElementTree as ET
def gen_srdf():
robot = ET.Element("robot", {"name": "sample_robot"})
ET.SubElement(
robot,
"virtual_joint",
{
"name": "fixed_base",
"type": "fixed",
"parent_frame": "world",
"child_link": "base_link",
},
)
arm = ET.SubElement(robot, "group", {"name": "manipulator"})
ET.SubElement(arm, "chain", {"base_link": "base_link", "tip_link": "tool0"})
gripper = ET.SubElement(robot, "group", {"name": "gripper"})
ET.SubElement(gripper, "joint", {"name": "finger_joint"})
ET.SubElement(
robot,
"end_effector",
{
"name": "gripper_eef",
"parent_link": "tool0",
"group": "gripper",
"parent_group": "manipulator",
},
)
home = ET.SubElement(robot, "group_state", {"name": "home", "group": "manipulator"})
ET.SubElement(home, "joint", {"name": "shoulder_pan_joint", "value": "0.0"})
ET.SubElement(
robot,
"disable_collisions",
{"link1": "base_link", "link2": "shoulder_link", "reason": "Adjacent"},
)
return {"xml": robot, "urdf": "sample_robot.urdf"}
```
Virtual and passive joints are valid SRDF concepts. The current lightweight runtime preserves them but does not yet fully inventory or validate them; verify them with MoveIt Setup Assistant or a MoveIt smoke test.
@@ -0,0 +1,37 @@
# SRDF implementation notes
These notes describe the current runtime shape so the documentation does not overstate what the code enforces.
## Implemented in the current code
- `scripts/srdf` generates explicit targets only.
- `gen_srdf()` must return an envelope with `xml` and `urdf`.
- Generated SRDF is validated against the linked URDF before writing.
- The CLI injects or updates local `tcad:urdf` metadata.
- Group states use `joint_values_by_name` / `jointValuesByName` in URDF-native units.
- Deprecated `joint_values_by_name_rad` / `jointValuesByNameRad` aliases remain for compatibility.
- Group-state values are checked for group membership, finite values, fixed/mimic status, and URDF limits when available.
- End-effector overlap and adjacency checks are implemented.
- Disabled-collision reasons are required and classified into broad provenance buckets.
- Optional CAD Viewer MoveIt2 controls use `protocolVersion: 1`.
- Pose targets support `quat_xyzw` and `rpy`.
- Position-only IK is explicit in request settings and defaults based on whether orientation is provided.
- Legacy degree fields are converted by joint type so prismatic values remain linear.
- Error responses sanitize absolute paths unless debug errors are enabled.
## Not yet fully implemented in code
The following remain process requirements and future code-improvement targets:
- full URDF structural validation shared with the URDF skill;
- virtual joint parsing and validation;
- passive joint parsing and exclusion from active planning variables;
- hard failure for disconnected chain base/tip definitions in every case;
- subgroup cycle detection as a first-class validation error;
- typed SRDF generation helpers;
- structured assumption/warning envelope fields;
- sampled self-collision matrix generation;
- full MoveIt configuration package generation;
- safer generator execution in a subprocess.
Until those are implemented, rely on the planning ledger, MoveIt Setup Assistant, `$cad-viewer` handoff for visual/MoveIt smoke tests when available, and explicit reporting of skipped checks.
@@ -0,0 +1,102 @@
# SRDF planning ledger
Create or update this ledger before writing SRDF XML. The ledger makes planning assumptions explicit and helps prevent plausible but incorrect MoveIt configurations.
## URDF dependency
| Field | Value |
|---|---|
| URDF path | |
| SRDF output path | |
| Robot name | |
| URDF validated? | yes/no; tool/check |
| Root link | |
| Active joints | |
| Fixed joints | |
| Mimic joints | |
| Passive joints | |
| Links used for collision checking | |
| Known URDF limitations | |
## Planning task
| Field | Value |
|---|---|
| Main task | IK / plan-to-pose / gripper / mobile base / dual arm / other |
| Primary planning group | |
| Expected end-effector or TCP | |
| Required solver or planner | |
| Position-only IK? | yes/no; reason |
| Orientation constraints? | yes/no; representation |
## Virtual joints
| Name | Type | Parent frame | Child link | Required? | Rationale |
|---|---|---|---|---|---|
| | fixed / planar / floating | | | | |
Virtual joints describe the robot root pose relative to an external frame. Use fixed for fixed-base manipulators when the planning setup needs a world attachment; use planar/floating only when the robot model requires that planning freedom.
## Passive joints
| Joint | URDF type | Reason passive | Affected groups | Notes |
|---|---|---|---|---|
| | | | | |
Passive joints are unactuated. They should not be treated as controllable planning variables.
## Planning groups
| Group | Representation | Members | Base link | Tip link | Active joints | Excluded joints | Purpose | Solver expectation |
|---|---|---|---|---|---|---|---|---|
| | joints / links / chain / subgroups | | | | | | | |
For serial arms, prefer a chain only when the URDF graph has a real path from base link to tip link. For subgroup groups, check for cycles and duplicate semantics.
## End effectors
| Name | End-effector group | Parent group | Parent link | Target/TCP link | Overlap checked? | Adjacent? | Notes |
|---|---|---|---|---|---|---|---|
| | | | | | | | |
The end-effector group should normally not share links with its parent group. The target/TCP link should be explicit when it differs from the inferred group tip.
## Group states
| State | Group | Joint values | Unit check | Limit check | Purpose |
|---|---|---|---|---|---|
| | | revolute/continuous rad; prismatic m | | | |
Do not store degrees in SRDF group states. Do not set fixed or mimic joints in group states.
## Disabled collisions
| Link 1 | Link 2 | Reason | Source | Evidence | Risk note |
|---|---|---|---|---|---|
| | | Adjacent / Never / Always / Default / Manual | Setup Assistant / sampled / adjacency / user | | |
Do not infer disabled collisions from visual impression. Each pair needs a reason and provenance.
## MoveIt smoke tests
| Test | Group | Target link | Target pose/state | Expected result | Actual result | Notes |
|---|---|---|---|---|---|---|
| IK solve | | | | | | |
| Plan-to-pose | | | | | | |
| Named state | | | | | | |
| Collision check | | | | | | |
## Assumptions to report
List every guessed or inferred value:
- planning group membership;
- chain base/tip;
- target/TCP link;
- virtual joint attachment;
- passive joint classification;
- group-state value;
- disabled collision pair;
- solver or planner setting;
- orientation/position-only IK assumption;
- skipped MoveIt validation.
@@ -0,0 +1,76 @@
# SRDF workflow
SRDF is the MoveIt semantic companion to a URDF. Keep physical robot structure, links, joints, geometry, inertials, mesh references, and limits in URDF. Keep planning semantics in SRDF.
## Edit loop
1. Start from a valid URDF. SRDF cannot repair wrong link frames, joint origins, limits, or geometry.
2. Find the Python source that defines `gen_srdf()`.
3. Treat that source as authoritative. Do not hand-edit generated `.srdf` output.
4. Fill or update the planning ledger.
5. Define virtual joints when the robot root needs a planning/world attachment.
6. Define passive joints for unactuated joints.
7. Define planning groups from URDF topology.
8. Define end effectors only after group membership is known.
9. Define group states in URDF-native units and check them against URDF limits.
10. Define disabled collisions only from adjacency, sampling, Setup Assistant output, or explicit user evidence.
11. Regenerate only the explicit SRDF target with `scripts/srdf`.
12. Hand generated or modified `.srdf` files to `$cad-viewer` for live viewer links when available.
13. Run MoveIt smoke tests when available. Use `$cad-viewer` for local Viewer-based IK or path-planning controls.
14. Report assumptions and skipped checks.
## Typical SRDF content
- `<virtual_joint>` entries for root/world attachment.
- `<passive_joint>` entries for unactuated joints.
- `<group>` planning groups, usually by joint list or chain.
- `<end_effector>` entries that connect a tool group to a parent planning group.
- `<group_state>` named joint states such as `home`.
- `<disable_collisions>` pairs for adjacent, sampled-safe, or intentionally ignored collisions.
## Planning groups
MoveIt acts on a selected planning group. Other joints are left stationary unless they belong to the selected group or are otherwise managed by the planning pipeline.
A group may be represented as:
- a collection of joints;
- a collection of links;
- a serial chain from base link to tip link;
- a collection of subgroups.
For serial chains, the base link is the parent link of the first joint in the chain, and the tip link is the child link of the last joint. Verify that the URDF graph actually contains that path.
## Group states
`<group_state>` values are stored in URDF-native units:
- revolute and continuous joints: radians;
- prismatic joints: meters.
The current runtime validates group-state values against group membership, fixed/mimic status, finite numeric values, and URDF limits when limits are available.
## End effectors
An end-effector is usually a separate tool or gripper group attached to a parent planning group. Avoid overlap between the end-effector group and the parent group. Record the target/TCP link in the planning ledger and in MoveIt2 request settings when it differs from the inferred group tip.
## Disabled collisions
`<disable_collisions>` pairs affect planning safety. Use truthful reasons:
- `Adjacent`;
- `Never`;
- `Always`;
- `Default`;
- `Setup Assistant sampled`;
- explicit manual rationale.
Do not generate broad disabled-collision lists from prose or visual appearance.
## CAD Viewer handoff and MoveIt2 controls
After creating or modifying generated `.srdf` files, hand the explicit output path to `$cad-viewer` for a live viewer link when that skill is available. SRDF does not own Viewer startup.
When the user needs local IK or path-planning controls, include that in the `$cad-viewer` handoff. CAD Viewer owns the local `moveit2_server`, including setup, environment checks, WebSocket URL wiring, and protocol details. Provide the SRDF path plus any known planning group, target/TCP link, target frame, pose, start state, and skipped assumptions.
The local server is a smoke-test helper, not a replacement for a full MoveIt configuration package.
@@ -0,0 +1,117 @@
# SRDF validation
Generation validates every `gen_srdf()` result against its linked URDF before writing. This catches many planning-semantics errors, but it is not a substitute for MoveIt Setup Assistant, MoveIt runtime tests, or collision-matrix sampling.
Generated or modified `.srdf` files should be handed to `$cad-viewer` for live viewer links when available.
## Current generation-time checks
The current runtime checks that:
- `gen_srdf()` returns an envelope dictionary;
- envelope fields are exactly `xml` and `urdf`;
- the URDF path is relative to the generator source, uses POSIX separators, ends in `.urdf`, and exists;
- SRDF XML parses and has root `<robot name="...">`;
- SRDF robot name matches the URDF robot name;
- local `tcad:urdf` metadata is injected or updated and matches the linked URDF path relative to the generated SRDF; legacy `explorer:urdf` metadata remains readable;
- at least one planning group exists;
- planning groups are named and unique;
- each planning group defines joints, links, chains, or subgroups;
- group joint names, link names, and subgroup names exist;
- chain base/tip links exist;
- end effectors reference existing parent links and groups;
- end-effector groups do not overlap their parent group when a parent group is provided;
- end-effector parent links are in the parent group or adjacent to the end-effector group;
- group states reference existing groups;
- group-state joints exist and belong to the selected group after group expansion;
- group-state values are finite;
- group states do not set fixed or mimic joints;
- revolute/prismatic group-state values are within URDF limits when limits are available;
- disabled collision pairs have distinct links, valid link references, non-empty reasons, and no reversed duplicates;
- many manually reasoned disabled collision pairs trigger a warning.
## Optional CAD Viewer MoveIt2 checks
When `$cad-viewer` starts its local MoveIt2 server for SRDF review, the server additionally checks:
- request `protocolVersion`;
- request type;
- repository-relative SRDF path and traversal safety;
- linked URDF path from `tcad:urdf` metadata;
- planning group selection;
- target frame and target link existence;
- target orientation shape and quaternion normalization;
- position-only IK consistency;
- native joint value parsing;
- legacy degree-field conversion by joint type;
- planner and IK setting basic numeric validity.
## Important current limitations
Do not treat a passing validation as proof of planning correctness. The current lightweight runtime does not fully validate:
- full URDF graph consistency; duplicate URDF links or joints can be collapsed by shallow inventory parsing;
- chain base/tip connectivity at generation time unless group-state expansion exposes the issue;
- subgroup cycles as hard errors in every path;
- `<virtual_joint>` inventory and validation;
- `<passive_joint>` inventory and exclusion from all active groups;
- collision matrix correctness through sampled self-collision analysis;
- actual IK solver availability for each group;
- actual planning success in the target MoveIt environment;
- controller configuration;
- full orientation-constraint behavior beyond request normalization.
Use MoveIt Setup Assistant or a MoveIt runtime smoke test for these checks.
## Manual planning checks
After generation, verify:
### URDF dependency
- URDF has been checked by the URDF workflow.
- URDF collision geometry is suitable for MoveIt collision checking.
- Active, fixed, mimic, and passive joints are understood.
### Planning groups
- Each chain has a real URDF path from base to tip.
- Each group contains the intended active joints and no accidental fixed/mimic/passive joints.
- Subgroups do not create ambiguous or cyclic group definitions.
- The selected planner/IK solver supports the group.
### End effectors
- End-effector group and parent group do not share links.
- Parent link is the real attachment point.
- Target/TCP link is explicit for pose requests.
### Group states
- Values use radians/meters, not degrees.
- Values are inside URDF limits.
- Named states are collision-free when intended.
### Disabled collisions
- Pairs came from adjacency, sampling, Setup Assistant output, or explicit user evidence.
- No broad disable list was invented by the model.
- Manual pairs were reviewed for safety.
## Validation report format
Use a compact report:
```text
Checks run:
- SRDF generation validation: passed
- linked URDF validation: previously passed with URDF skill
- CAD Viewer link: returned
- MoveIt Setup Assistant review: skipped, unavailable
- CAD Viewer MoveIt2 IK smoke test: passed for manipulator/tool0
- collision matrix sampling: skipped, no MoveIt environment
Assumptions:
- Assumed tool0 is the desired TCP.
- Disabled collisions are adjacency-only.
```