# Day 1 实验包：生成方块模型，修好坐标与盒子

需要 Python 3.9+。仅使用标准库，不需要 GPU、不需要 pip 安装。Mac / Linux 通常使用 python3；Windows 若使用官方启动器，可将 python3 替换为 py -3。

## 先认清三个文件

- `scene-broken.json`：场景设置，用普通文本编辑器打开。JSON 用字段名和数值保存设置，修改时保留引号、逗号和括号。
- `scene_lab.py`：读取设置并生成报告的 Python 程序，本课不用修改。
- `.obj`：程序生成的三维模型文件，可以导入 Blender。

可在已有 Python 的云端开发环境（例如 GitHub Codespaces）中上传、解压并运行，不需要这台电脑承担网站服务。下列命令都要在解压后的实验文件夹里执行。

## 1. 先制造一个可复现的失败（10 分钟）

解压后在本目录打开终端：

```sh
python3 scene_lab.py scene-broken.json --out before
```

第一次运行应得到两个 FAIL，一个 PASS，位置误差约 916.515 mm；它表示两组三维位置之间的直线距离，本课不用手算这个数。退出码 1 是实验故意设计的检查失败，不是安装失败。生成的文件在 before 目录。

此脚本做坐标变换和静态几何检查，不进行接触求解、抓取、轨迹规划或训练。

命令中 `python3` 是运行程序的工具；`scene_lab.py` 是程序名；`scene-broken.json` 是输入设置；`--out before` 指定把结果写进 before 文件夹。先打开 `before/report.md`，找到位置和碰撞两项失败。

## 2. 修复并解释（15 分钟）

复制 scene-broken.json 为 scene-fixed.json。用普通文本编辑器修改，保持 JSON 语法：

1. 保留 `command.frame` 为 `world`，把 `command.position` 改成 `[0.5, 0.9, 0.2]`，单位仍为 `m`。前两个数就是网页的旋转算例；第三个数是高度：相机高 0.4 米，观测点在其下方 0.2 米，所以世界高度为 0.4 − 0.2 = 0.2 米。
2. 将 bin_collision 从 solid 改成 walls，保留料盒内腔。
3. 不修改相机真实位姿，也不修改观测点来迎合错误命令。

```sh
python3 scene_lab.py scene-fixed.json --out after
```

验收：三个 PASS；坐标误差接近 0；能解释为什么只修改数字、不说明 frame，仍可能错。

## 3. 做一次单位对照（10 分钟）

复制修好的配置为 scene-mm.json，将 command.position 的三个分量都乘 1000，同时把 command.unit 设成 mm。运行到 after-mm 目录，坐标检查应仍然通过。

再从 `scene-fixed.json` 复制一份 `scene-wrong-unit.json`，只把 unit 从 m 改成 mm，不改数值。注意从米制配置复制，不要从已经正确转换的 scene-mm.json 复制。运行到 wrong-unit：

```sh
python3 scene_lab.py scene-mm.json --out after-mm
python3 scene_lab.py scene-wrong-unit.json --out wrong-unit
```

误差应增大。保留两份 report.json 作对照。

## 4. 可选：在 Blender 中真正看资产（20–30 分钟）

需要自己已有 Blender；此步骤无需 GPU 训练环境。本实验没有替你安装 Blender，也未宣称运行过 Blender GUI。

1. 新建空场景，使用 File → Import → Wavefront (.obj) 导入 before/bin_visual.obj。文件单位是米、Z-up；若导入器要求 Forward / Up，选择 Y Forward、Z Up，不额外缩放。
2. 导入 before/bin_collision.obj。所有 OBJ 都在对象局部原点，因此外观与碰撞文件会叠在一起。它们不会自动加载 scene.json 的世界位置。
3. 在 Outliner 中选中碰撞对象，在 Object Properties → Viewport Display 中将 Display As 设成 Wire（也可逐个隐藏对象比较）。从上方观察，实心外包覆盖了内腔。
4. 隐藏旧碰撞对象，导入 after/bin_collision.obj。组合碰撞体保留了内腔，能看到差异。导入器可能按对象名拆分成多个对象，全部选中对应对象即可。
5. 再导入 after/part.obj，确认它是边长 0.04 m 的立方体。进入 Edit Mode 看顶点和三角面。要复原完整场景，可按 scene.json 的 world_position 手动设置 Location。
6. 另存为 day01.blend，截取“错误碰撞体”“修复碰撞体”两张对照图。

注意：文件名叫 collision 不会自动让它成为 Blender 的物理碰撞体。本步仅检查几何；刚体与求解器在后续课程中配置。

## 输出说明

- part.obj：真实可导入的三角网格，8 个顶点、12 个三角面。
- bin_visual.obj：底板与四面盒壁，40 个顶点、60 个三角面。
- bin_collision.obj：取决于配置，生成实心外包或五个盒体。
- scene.json：本实验自定义的清晰可读清单，不是任何仿真器的原生配置。
- report.json / report.md：实际检查结果，不是预填答案。

已有输出目录中同名生成文件会被覆盖；使用不同 --out 路径保留每次实验。

## 交付与完成标准

保留 before、after、after-mm、wrong-unit 四次结果；写 150 字解释坐标系、单位与碰撞内腔分别解决什么问题。只运行正确配置一次，不算完成对照实验。

参考答案（完成后再看）：相机原点 [0.6,0.6,0.4]，绕 Z 轴正向旋转 90°；相机点 [0.3,0.1,-0.2] 变到世界为 [0.5,0.9,0.2]。
