AI 协作日志

学生 Web 实验作品平台

学号:202412215401032 · 来源:ai-log.md

# 实验四 AI协作与核验记录

AI工具:ChatGPT(网页版对话)

## 协作1:变换次序核验(Task B)

**我的目标和预先预测**
Task B 要比较 `T·Ry·S` 和 `Ry·T·S` 两种次序。我先自己预测:`T` 在左边时,平移是最后一步,所以局部原点的世界坐标应该正好等于平移量 `(tx,0,0)`;`R` 换到左边时,被平移之后的点还要整体绕 Y 轴转一次,所以会跑到别处。但我对 z 的正负号一直没把握(是 `+tx·sinθ` 还是 `-tx·sinθ`),所以带着自己写的预测去问 AI。

**关键提示词(原文)**
> T·R 和 R·T 到底差在哪,能举个坐标例子吗?z 的正负号我老搞混

**AI建议摘要**
- 列向量约定下连乘右边先执行:`T·R·S` 是先缩放、再旋转、最后平移;`R·T·S` 是先缩放、再平移、最后整体旋转。
- 作用在局部原点上时:`T·R·S` 得到 `(tx,0,0)`;`R·T·S` 得到 `(tx·cosθ, 0, -tx·sinθ)`,z 分量是**负**的 sin。

**我的判断**
AI 给出的和我预测的方向一致,但我没有直接照抄结论——我在 task-b.js 里**另外写了一条独立的手算公式**(就是上面那个 `(tx·cosθ,0,-tx·sinθ)`),和 `CG4.chain` 链乘出来的结果做交叉比对,让状态栏同时打印"程序值 / 手算值 / ✓或✗"。这样万一我把次序写反了,两条就会对不上。另外我自己想到一个补充:当 θ=0°(或 tx=0)时两种次序会**偶然重合**,所以不能拿"看起来一样"当证据说明乘法可交换,这一点我也测了。

**测试与结果(已运行核验)**
固定 tx=2、θ=90°、s=1 点「一键设置90°测试」:
- `T·R·S` 中心 `(2.00, 0.00, 0.00)`,手算值相同,✓
- `R·T·S` 中心 `(0.00, 0.00, -2.00)`,手算值相同,✓

和指导书第 124 行给的验收数据完全一致。另外单独把 θ 改成 0°,画面上两只立方体确实重叠在一起——证明是"偶然重合"而不是乘法可交换。

**修正结论**
没有推翻 AI 的结论,但把我原来弄反的 z 符号彻底纠正了(是 `-tx·sinθ`)。也正因为加了手算对照这一步,才敢确定我的 `chain()` 参数顺序没写错。

## 协作2:程序调试(Task C / Task D)

**错误现象与触发背景**
这一步我没有等到程序崩溃。因为写完之后我想确认自己是不是真的理解了两条最容易写错的规则,就按指导书允许的做法,**主动制造了两处可恢复的矩阵错误,测出症状后再改回来**。整个过程是真实跑出来的,不是空想。

**我先自己的假设(后来被证明是错的)**
1. 绕点旋转里 `T(-P)` 感觉可有可无,反正最后是 `T(P)` 平移回去;
2. Task D 里把已经含缩放的臂段绘制矩阵 `armDraw` 直接当作父级位姿传给下一层,应该也能工作。

**关键提示词(原文)**
> 绕点旋转里漏掉 T(-P) 会怎么样?还有父子链上层把非均匀缩放传下去,会出现什么症状?

**AI列出的候选原因与排查办法**
- 候选A:`T(-P)` 缺失时,旋转中心会从 P 漂移到世界原点,物体不再绕 P。
- 候选B:非均匀缩放会同时拉伸局部坐标轴,若混进位姿传给下一层,子对象的偏移量会被按比例放大。
- 建议:用"点到 P 的距离是否恒定"和"肩到末端的距离是否恒等于臂长"这两个不变量来判断。

**我逐项测试的结果(真实数值)**
错误1|Task C,故意写成 `T(P)·Ry·T(q)·S`(漏掉 `T(-P)`),取 P=(1,0,1)、q=(2,0,0)、θ=90°:
- 正确版本:中心 `(0.00, 0.00, 0.00)`,到 P 的距离 `1.414`(等于 |q-P|,恒定)
- 错误版本:中心 `(1.00, 0.00, -1.00)`,到 P 的距离变成 `2.000`
→ 症状很直观:物体没有绕 P 转,而是绕世界原点转了一下再被平移,旋转中心漂掉了。

错误2|Task D,故意写成 `tip = armDraw·T(0,2.2,0)`(把含 `S(.38,2.2,.45)` 的绘制矩阵当父位姿):
- 正确版本:肩—末端距离 `2.200`(等于臂长)
- 错误版本:肩—末端距离变成 `5.940`
→ 症状:探头像被拉长了一大截飞出去,因为臂段 Y 向 2.2 倍的缩放把 `T(0,2.2,0)` 也放大了。

**真正原因、修改位置与复测结论**
- 真正原因:`T(-P)` 是把 P 临时挪到原点、旋转完再挪回去的关键一环;非均匀缩放必须只留在"绘制矩阵"的最末端,不能进入"位姿矩阵"。
- 修改位置:`js/task-c.js` 的 `orbitModel`(恢复 `T(P)·Ry·T(-P)·T(q)·S` 五段);`js/task-d.js` 与 `js/task-e.js` 里末端关节改为继承 `shoulderPose` 而不是 `armDraw`。
- 复测:恢复后 yaw=0、pitch=0 时肩部 `(0.00, -0.75, 0.00)`、末端 `(0.00, 1.45, 0.00)`、距离 `2.200`,全部回到正确值。两个不变量(到 P 的距离恒定、肩到末端的距离恒定)我也直接做进了状态栏,随时能看。

**额外收获**
这条"距离不变量"后来成了我验收的主要手段:画面看着差不多的情况,数字会直接告诉我矩阵关系对不对——指导书第 261 行那句"画面看上去大致正确不等于矩阵关系已被验证"我算是真的体会到了。

## 协作3:设计协商(Task E)

**待解决的具体设计问题**
Task E 的起始场景就是教师的示例(医学设备定位+旋转样本台),我怕只把 TODO 填完就交会被判成照搬示例。但我也不想推翻整个结构冒险,所以去和 AI 商量"怎么改才算真的改了"。

**关键提示词(原文)**
> 还是这个机械臂主题的话,怎么改才不算只换个颜色?给两个省时间的改法

**两种方案及取舍依据**
- 方案A:换成"行星—卫星系统"主题,中心天体自转、卫星公转、再加一颗卫卫星做父子链。主题差异最大,但整套部件位置要重新排,40 分钟内风险高、也容易在调坐标上耗时间。
- 方案B:保留原来的基座—机械臂—探头结构,但**新增第三个关节自由度"探头伸缩"**,让 `extend` 直接参与位姿:`M_tip = M_shoulder · T(0, L+extend, 0)`。
- 取舍:选 B。理由是不是改颜色改数量,而是**改了矩阵链本身**——`extend` 出现在位姿里,所以探头永远沿机械臂轴线伸出、并跟随基座偏航和肩部俯仰;这个差异用坐标数字能直接验证。而且改动面小、失败风险低。AI 也提醒我"至少得有一个能从矩阵关系上说明的差异,而不是加一个立方体",这点我采纳了。

**我最终采用的实现与矩阵链**
- 基座:`M_base = T(-2,-1.3,0) · Ry(yaw)`
- 肩部:`M_shoulder = M_base · T(0,.55,0) · Rz(pitch)`
- 末端(新增):`M_tip = M_shoulder · T(0, 2.2+extend, 0)`
- 探头绘制:`M_probe = M_tip · T(0,.325,0) · S(.73,.65,.73)`
- 样本自转:`T(P) · Ry(θ_spin) · S(.7,.78,.7)`,中心不动
- 标记公转:`T(P) · Ry(θ_orbit) · T(1.16,.28,0) · S(.22)`,中心绕圆

三种复合机制同时在场:两级父子继承、自转、绕点公转;独立可调参数有 yaw、pitch、extend、speed 四个。

**测试与反思(两个参数状态的预期/实际对照)**

| 参数状态 | 预期 | 实测 |
|---|---|---|
| yaw=0, pitch=0, extend=0 | 末端 `(-2, 1.45, 0)`;肩—末端=2.20 | 末端 `(-2.00, 1.45, 0.00)`;距离 `2.200` ✓ |
| yaw=90, pitch=30, extend=0.8 | 末端被父级带动离开原位;肩—末端=3.00 | 末端 `(-2.00, 1.85, 1.50)`;距离 `3.000` ✓ |
| yaw=-60, pitch=-30, extend=0.4 | 肩—末端=2.60 | 末端 `(-1.35, 1.50, 1.13)`;距离 `2.600` ✓ |

另外三个可核验不变量:肩部坐标恒为 `(-2.00, -0.75, 0.00)`(它在偏航轴上,父级转动不会移动它);样本自转时中心始终为 `(2,-.48,0)` 不动;标记到样本中心的 XZ 半径恒为 `1.16`。这些我都做进了状态栏实时显示。

反思:一开始我以为"加个滑块"就算自主创作,后来意识到只有让这个参数**进入位姿矩阵**、改变了父子链,才算真的修改了结构。这也是我最后选 extend 而不是随便加个装饰立方体的原因。

## 其他使用AI的记录
- Task A 的复合矩阵 `T·Ry·S`:AI 帮我确认了"列向量下右侧先执行"所以 S 最先作用。我在页面状态栏加了"预测中心 vs 实际中心"的对照,改 s 或 θ 时中心始终等于 `(tx,ty,tz)`,用来自证次序没写反。
- Task C 的角度推进:AI 提醒我暂停期间不要累加 elapsed、也不要额外新建 requestAnimationFrame 循环;我沿用实验三的 dt 写法,每帧从当前角度重建矩阵而不是在旧矩阵上累乘,所以没有漂移。