Skip to content

docs: add AGENTS.md — guidance for coding agents driving DEEPRobotics robots - #4

Open
armwaheed wants to merge 1 commit into
DeepRoboticsLab:mainfrom
armwaheed:add-agents-md
Open

docs: add AGENTS.md — guidance for coding agents driving DEEPRobotics robots#4
armwaheed wants to merge 1 commit into
DeepRoboticsLab:mainfrom
armwaheed:add-agents-md

Conversation

@armwaheed

@armwaheed armwaheed commented Sep 3, 2026

Copy link
Copy Markdown

@CcShuo — flagging this for you, since you were in the room for the session it came from. (We do not have permission to set assignees on this repository, so this mention stands in for assigning it.)

English below · 简体中文 in the second half. Both halves are complete; neither is a summary of the other.


English

Hello — this comes from the DR02 Pro bring-up session on 3 September 2026. Thank you again for the time on the day, and for the SDK: everything in this PR was found while using it successfully, which is why it is offered as a contribution rather than as a bug report.

What this adds

Two new files and a four-line pointer from each README:

File What it is
AGENTS.md Instructions for a coding agent working with this SDK
AGENTS_CN.md The same document in 简体中文, following the repository's existing bilingual convention
README.md, README_CN.md One short section pointing at it

No source, no examples, no documentation under src/ is touched.

What an AGENTS.md is

AGENTS.md is a convention that coding agents — Claude Code, Codex, Cursor, and others — read automatically from a repository root before they write anything. It is not documentation for people to browse. It is a set of instructions an agent will follow literally, so it is written in the imperative, states why each rule exists, and cites the file in this repository that each value came from.

It does not duplicate your documentation. Every value it quotes is cited back to your file — src/dr02_pro/docs/JOINT_CONTROL.md, src/dr02_pro/low_level/arm_joint_example.cpp, src/dr02_pro/docs/DEVELOPER_MODE.md — so that if the two ever disagree, the file says outright that your document is right and AGENTS.md is stale.

Why it exists

A coding agent fails differently from a person, and this SDK's failure modes are the exact shape that hurts it most.

An agent reads a successful return value as success. Almost nothing in this file produces an unsuccessful return value. A /STEER message publishes, appears on the wire with the right values, shows connected subscribers, and the robot stands still. A /JOINTS_CMD array is accepted in full and moves a joint that was never named. A topic lists, reports a type, and delivers zero bytes. None of these raise an error, so an agent's next move is to change the value it sent — which is almost always the wrong hypothesis, and on this machine an expensive one.

We lost most of a day to that pattern, and we dropped the robot twice, both times through our own mistake. This file is an attempt to make the next team's day cost less.

What it would have saved

Honestly, most of the day. In order of what cost the most:

  1. Arm work requires Upper-Body Joint Control Mode. We spent time in High-Level before establishing that /ACTION is twelve preset gestures on the Pro (five on the Std) with no grasp, lift or carry, and that in High-Level the internal policy owns the joints. This is all in EXAMPLES.md — but it is spread across a table of actions and a table of modes, and an agent planning a manipulation task reads "there is an action interface" and starts there. The file now says the conclusion in one line, at the top.

  2. /STEER is accepted in Upper-Body mode, which is the single most useful thing we learned. Your own example table lists steer_example under both modes, and it means the robot can walk on its own leg policy while the SDK owns the waist and both arms — one mode, no mid-run switch. Since modes cannot be switched from inside a running program, that is not a convenience; it is the difference between a task being possible and not. We measured a single-arm reach tracking to 0.11° while the walking policy held the legs.

  3. The legs are kept by zero gain, not by not naming them. This is what dropped the robot. /JOINTS_CMD is full length, so every joint gets an entry whether it was named or not, and a position entry with a non-zero kp is an active command that fights the walking policy. We applied a uniform kp=40 across all 31 entries; the arm moved a little and the legs collapsed. Our own guard checked which joints the caller had named — and the legs were never named. src/dr02_pro/low_level/arm_joint_example.cpp already does this correctly, with kp = kd = 0 from index 17 onward; we did not read it closely enough to see that the zero was the load-bearing part rather than a placeholder.

  4. The gains are a table and so is the damping. waist_x_joint wants 2800 and a wrist wants 90 — a factor of thirty-one inside one array. We used one number for the whole array. Then, with the gains fixed, we derived kd as kp/20, which on waist_x_joint gives 140 against your 15, and the waist bent sideways during a two-armed reach. Both arrays are published in your example; we simply had not quoted them.

  5. We read the wrong variant's document. The gains that folded the robot came from dr02_std/low_level/arm_joint_example.cpp, and the robot was a Pro. dr02_pro/ and dr02_std/ are sibling directories with identical filenames, differing joint counts, arm degrees of freedom and gains — and nothing on the wire tells you which robot you are holding, since /JOINTS_CMD carries a bare array with no model field. The file therefore opens the DR02 section with "measure the joint count first" and puts both index tables side by side. 31 is a Pro, 21 is a Std, anything else means stop and ask.

On the things outside your documentation

Several entries concern robot-image software rather than this SDK — the DDS profile script that has to be sourced before topics deliver bytes, /JOINTS_DATA_10HZ, the RTSP head camera, the LiDAR field of view. These are outside what the SDK could reasonably be expected to document, and the file says so where it says them. They are recorded only because an agent will meet them and will otherwise attribute them to its own code.

Where your documentation already warns about something, we say so and point at it rather than restating it as a discovery. CAMERA.md's warning that the serial-to-position mapping cannot be determined from serials is correct, and we only add that the USB descriptor serial is not the firmware serial, and that the empirical method is weaker than it sounds because one downward-angled view of bare floor looks much like another.

Two things we would value a correction on

Both are written in the file as open questions, not findings, and both can be replaced with a link to your documentation if one exists:

  • /STEER was ignored until we left the header unset. In RLControl with a gait, feet on the ground, QoS matched, no competing publisher, correct values visible on the wire — 293 commands across three attempts, no motion, no log line. A capture of the handheld controller showed every message carrying frame_id: 0 and an unset stamp. Publishing with frame_id = 0 and a default stamp moved the robot on the first attempt. We changed both fields together, so we cannot say which one mattered. Our guess is that the consumer validates the stamp against the robot's clock and our publisher was on a development host — which would be consistent with steer_example working, since it sets both fields and normally runs where the clocks agree. If that is documented somewhere we did not find, we would rather delete the entry and link to it.

  • /JOINTS_DATA did not decode for us while /JOINTS_DATA_10HZ did — 0/5 against 5/5, failing inside the DDS reader before any ROS conversion, and --raw failed identically. We observed this only through ros2 topic echo from a Python subscriber. We did not run your arm_joint_example, which subscribes /JOINTS_DATA in C++, so we cannot say whether it is affected and it may well not be. The file says exactly that. If the C++ path is fine, the difference between the two is itself worth knowing.

Attribution and limits, stated in the file itself

  • Everything measured is marked with the date it was taken. The DR02 material is one robot, one afternoon, one network — 3 September 2026. The file says plainly that this is not a population and that the shape of each problem is more likely to generalise than the values.
  • Nothing was verified on a DR02 Std. The Std tables are quoted from src/dr02_std/ and are labelled unverified throughout.
  • Every number is either cited to a path in this repository or carries a measurement date. The closing section makes that a rule for anyone adding to the file.

Structure, and adding robots later

A common section (§3 for any robot, §4 for anything speaking drdds), then one section per product: §5 DR02 (Pro and Std), §6 Lite3. §7 is a short template for adding the next one, with the six questions a product section should answer.

§6 covers a robot that is not in this repository, and is written that way — it exists so that an agent which has read the DR02 sections and then meets a Lite3 knows the model in its head is wrong: UDP rather than ROS 2 topics, no Developer Mode, and the opposite answer to what happens when the sending process is killed. It is drawn from work on two Lite3 Venture units in August–September 2026. If you would rather this repository stay DR02-only, say so and we will drop §6 and the Lite3 rows from the contents — the rest stands without it.

Happy to split this, cut it down, or change the tone anywhere it reads wrongly. It is a document about how to use your SDK well, and you are the authority on every value in it.


简体中文

您好 —— 本 PR 来自 2026 年 9 月 3 日的 DR02 Pro 调试上电。再次感谢当天的时间,也感谢这套 SDK:本 PR 中的所有内容,都是在成功使用它的过程中发现的,这也是我们把它作为一份贡献、而不是一份缺陷报告提交的原因。

本 PR 添加了什么

两个新文件,以及两个 README 中各四行的指引:

文件 说明
AGENTS.md 给使用本 SDK 的编码代理的说明
AGENTS_CN.md 同一文档的简体中文版,遵循本仓库既有的双语约定
README.mdREADME_CN.md 一小节指向它的入口

不改动 src/ 下的任何源码、示例或文档。

AGENTS.md 是什么

AGENTS.md 是一项约定:编码代理(Claude Code、Codex、Cursor 等)在动手写任何东西之前,会自动从仓库根目录读取它。它不是供人浏览的文档,而是代理会按字面执行的一组指令。因此它使用祈使语气,说明每条规则为什么存在,并注明每个数值来自本仓库中的哪个文件。

它不重复贵方的文档。它引用的每一个数值都标注了来源 —— src/dr02_pro/docs/JOINT_CONTROL_CN.mdsrc/dr02_pro/low_level/arm_joint_example.cppsrc/dr02_pro/docs/DEVELOPER_MODE_CN.md —— 并且明确写道:如果两者出现分歧,以贵方文档为准,AGENTS.md 即为过时。

它为什么存在

编码代理的失败方式与人不同,而本 SDK 的失效形态恰恰是对代理伤害最大的那一类。

代理会把成功的返回值读作成功。 而本文中几乎没有一件事会产生不成功的返回值:一条 /STEER 消息发布成功、在通信上能看到正确数值、订阅方显示已连接,而机器人站着不动;一个 /JOINTS_CMD 数组被完整接受,却驱动了一个从未被点名的关节;一个 Topic 能列出、能报告类型、却传输零字节。这些都不会报错,于是代理的下一步动作是去修改自己发送的数值 —— 而这几乎总是错误的假设,在这台机器上还是代价高昂的假设。

我们因为这个模式损失了大半天时间,并且两次把机器人放倒,两次都是我们自己的错误。这份文件是一次尝试,希望让下一支队伍的一天少花一些代价。

它本可以省下什么

坦率地说,大半天。按代价从大到小排列:

  1. 手臂作业必须使用上半身关节控制模式。 我们在高层模式上花了时间,之后才确认 /ACTION 在 Pro 上是十二个预置动作(Std 上是五个),没有抓取、举起或搬运,而且高层模式下关节由内部策略控制。这些内容 EXAMPLES_CN.md 里都有 —— 但它们分散在"动作表"和"模式表"两处,而一个在规划操作作业的代理,读到"这里有一个动作接口"就会从那里入手。现在这份文件把结论用一行写在最前面。

  2. /STEER 在上半身模式下同样被接受,这是我们学到的最有用的一件事。贵方自己的示例表格就把 steer_example 同时列在两种模式下 —— 这意味着机器人可以依靠自身腿部策略行走,同时由 SDK 控制腰部和双臂,同一个模式、中途无需切换。由于模式无法在程序运行中切换,这不是一项便利,而是"任务能否成立"的分界。我们实测到:在行走策略托住双腿的同时,单臂伸展的跟踪误差为 0.11°。

  3. 保住腿部靠的是零增益,不是不点名。 这就是机器人被放倒的原因。/JOINTS_CMD 是全长数组,无论是否点名每个关节都会得到一个条目,而一个 kp 非零的位置项就是一条与行走策略对抗的主动指令。我们对全部 31 个条目统一施加了 kp=40:手臂只动了一点,双腿塌了下去。我们自己的防护检查的是调用方点名了哪些关节 —— 而腿从来没有被点名。src/dr02_pro/low_level/arm_joint_example.cpp 本来就是正确的,从索引 17 起 kp = kd = 0;是我们读得不够仔细,没有看出那个零才是承重的部分,而不是一个占位值。

  4. 增益是一张表,阻尼也是一张表。 waist_x_joint 需要 2800,腕关节需要 90 —— 同一个数组内相差三十一倍,而我们对整个数组用了一个数。之后增益改对了,我们又把 kdkp/20 推导,在 waist_x_joint 上得到 140(贵方规格是 15),结果双臂伸展时腰部向侧向弯曲。这两张数组在贵方示例中都是公开的,我们只是没有照抄。

  5. 我们读错了型号对应的文档。 让机器人折叠的那组增益来自 dr02_std/low_level/arm_joint_example.cpp,而机器人是一台 Pro。dr02_pro/dr02_std/ 是并列目录、文件名完全相同,而关节数、手臂自由度和增益都不同 —— 并且通信上没有任何东西会告诉你手上是哪一台,因为 /JOINTS_CMD 传输的是不含机型字段的裸数组。因此这份文件在 DR02 一节开头就写"先测关节数",并把两张索引表并排列出。31 是 Pro,21 是 Std,其他任何数值都意味着停下来提问。

关于贵方文档范围之外的内容

有若干条目涉及的是机器人镜像中的软件,而不是本 SDK —— 那个必须先 source 才能让 Topic 传输字节的 DDS 配置脚本、/JOINTS_DATA_10HZ、RTSP 头部相机、LiDAR 的视场范围。这些超出了本 SDK 理应记录的范围,文件在写到它们的地方也如实说明了这一点。记录它们,只是因为代理一定会遇到,而且否则会把问题归咎于自己的代码。

凡是贵方文档已经给出警告的地方,我们都写明并指向它,而不是把它当作新发现重述。 CAMERA_CN.md 中"序列号与安装位置的对应关系无法从序列号本身确定"这条警告是正确的;我们只补充两点:USB 描述符序列号不是固件序列号;以及"凭经验建立对应关系"这件事比听上去更脆弱 —— 一台朝下的相机拍到的空地板,和另一台朝下的相机拍到的空地板长得很像。

有两件事,我们非常希望得到指正

这两条在文件中都是以开放问题而非结论的形式写的;如果贵方已有相应文档,它们都可以直接替换为一个链接:

  • 在把消息头留空之前,/STEER 一直被忽略。RLControl、已选步态、双脚触地、QoS 匹配、无其他发布者、通信上能看到正确数值的条件下 —— 三次尝试共 293 条指令,没有运动,没有任何一行日志。对手柄成功驱动机器人时的抓包显示,每条消息都携带 frame_id: 0 和未设置的 stamp。改为 frame_id = 0 且 stamp 保持默认后,第一次尝试机器人就动了。两个字段是一起改的,因此我们无法判断是哪一个起了作用。我们的猜测是:消费方会用机器人的时钟校验时间戳,而我们的发布端在一台开发主机上 —— 这也能解释 steer_example 为什么正常工作,因为它设置了这两个字段,而它通常运行在时钟一致的环境里。如果这一点在某处已有文档而我们没有找到,我们更愿意删掉这一段并链接过去。

  • /JOINTS_DATA 在我们这里无法解析,而 /JOINTS_DATA_10HZ 可以 —— 0/5 对 5/5,在进入任何 ROS 转换之前就在 DDS reader 内部失败,--raw 同样失败。我们只通过 Python 侧订阅者用 ros2 topic echo 观察到这一点。我们没有运行贵方的 arm_joint_example(它以 C++ 订阅 /JOINTS_DATA,因此无法判断它是否受影响,而且很可能并不受影响。文件里写的正是这句话。如果 C++ 路径没有问题,那么这两条路径之间的差异本身就值得了解。

出处与边界,文件本身已写明

  • 所有实测内容都标注了测量日期。DR02 部分是 一台机器人、一个下午、一个网络 —— 2026 年 9 月 3 日。文件明确写道:这不构成统计样本,每个问题的形态比其数值更可能具有普遍性。
  • 没有任何内容在 DR02 Std 上验证过。 Std 的表格引自 src/dr02_std/,全文都标注为未经实机验证。
  • 每一个数字,要么引自本仓库中的某个路径,要么带有一个测量日期。文件的最后一节把这一点定为今后向本文添加内容时的规则

结构,以及后续如何添加机型

先是通用部分(§3 适用于任何机器人,§4 适用于任何使用 drdds 的机器人),然后按产品分节:§5 DR02(Pro 与 Std),§6 Lite3。§7 是一个简短的模板,列出新增一节应当回答的六个问题。

§6 涉及的机器人并不在本仓库中,文件也是这样写的 —— 它存在的意义,是让一个读完 DR02 部分、随后遇到 Lite3 的代理知道自己脑中的模型是错的:UDP 而非 ROS 2 Topic、没有开发者模式,而且"发送进程被杀死时会发生什么"的答案正好相反。该节来自 2026 年 8—9 月对两台 Lite3 Venture 的集成工作。如果贵方希望本仓库只保留 DR02 内容,请告知,我们会删去 §6 及目录中的 Lite3 条目 —— 其余部分不依赖它。

如果需要拆分、精简,或任何措辞读起来不妥,我们都很乐意修改。这是一份关于如何用好贵方 SDK 的文档,其中每一个数值的最终权威都是贵方。

… robots

Adds a root AGENTS.md (and the matching AGENTS_CN.md) recording the SDK
behaviours that a coding agent has to know before it writes a command,
and that produce no error when they are got wrong.

Structure is a common section that should hold for any DEEPRobotics
robot, then one section per product, so further products can be added
without reorganising the file. Starts with DR02 (Pro and Std) and Lite3.

Content is of two kinds and is marked as such throughout: values quoted
from files in this repository, which can be checked in a diff; and
observations measured on hardware, each carrying the date it was taken.
Nothing was verified on a DR02 Std, and that is said where it applies.

Also adds a short pointer to the file from both READMEs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants