robot-notes — 機器人知識筆記 GitHub ↗
本章與本頁目次

關於

robot-notes /關於/整理計畫與進度

robot-notes 整理計畫(PLAN)

把機器人知識「從軟體到硬體」完整整理成一套可在 GitHub 上隨時閱讀的筆記。以送餐機器人(室內 AMR)為主軸,逐步擴展到調度軟體、主板模擬與 Physical AI。

每個主題一個 markdown,README.md 當索引入口。每完成一輪就更新 GitHub,並請「專家」與「學生」兩個角色的 agent 讀過新文件,確認清楚到能讓人快速理解。


目錄結構

robot-notes/
├── README.md                 # 索引入口(GitHub 首頁)
├── PLAN.md                   # 本檔:整理計畫與進度
├── CONTEXT.md                # 術語表(ubiquitous language)
├── img/                      # 概念圖與示意圖(SVG 為主)
└── docs/
    ├── 00-overview/       # 系統全貌
    │   └── system-architecture.md
    ├── 10-core/           # 共通核心 —— 換了形態也還在
    │   ├── README.md
    │   ├── 10-hardware/   # 硬體:電怎麼變成力矩、感測器怎麼把物理量變成數字
    │   │   ├── README.md
    │   │   ├── communication-buses.md
    │   │   ├── digital-circuits.md
    │   │   ├── encoders.md
    │   │   ├── lidar-landscape.md
    │   │   ├── motors-and-foc.md
    │   │   ├── power-and-safety.md
    │   │   └── sensors.md
    │   ├── 20-firmware/   # 韌體:意圖怎麼變成馬達實際在轉
    │   │   ├── README.md
    │   │   ├── board-simulation-renode.md
    │   │   ├── host-mcu-protocol.md
    │   │   ├── low-level-control.md
    │   │   └── stm32-rest-tls.md
    │   └── 30-navigation/ # 導航:我在哪、地圖長什麼樣、怎麼從 A 到 B
    │       ├── README.md
    │       ├── kinematics-and-coordinate-transforms.md
    │       ├── nav2-plugin-algorithms.md
    │       ├── localization.md
    │       ├── path-planning.md
    │       ├── path-smoothing-and-trajectory.md
    │       ├── slam-3d-lidar.md
    │       └── slam-mapping.md
    ├── 20-forms/          # 形態分支 —— 換了形態就得換
    │   ├── README.md
    │   ├── legged/        # 四足
    │   │   ├── README.md
    │   │   ├── gait-and-actuation.md
    │   │   └── legged-fundamentals.md
    │   ├── mobile-manipulator/ # 搬運車 + 機械手臂
    │   │   ├── README.md
    │   │   ├── arm-kinematics.md
    │   │   └── mobile-manipulation.md
    │   └── wheeled-amr/   # 輪式 AMR
    │       ├── README.md
    │       └── chassis-and-drivetrain.md
    ├── 40-fleet/          # 多機調度
    │   ├── README.md
    │   ├── indoor-amr-roadnet-selection.md
    │   ├── mqtt-tls-emqx.md
    │   ├── open-rmf.md
    │   ├── proprietary-vs-ros2-arbitrary-start.md
    │   ├── rmf-adapter-cookbook.md
    │   ├── rmf-maps-and-traffic.md
    │   ├── rmf-multi-container-deploy.md
    │   ├── roadnet-and-traffic-control.md
    │   ├── robot-wan-5g-satellite.md
    │   ├── ros2-dds-intro.md
    │   ├── slot-reservation-dispatch-strategies.md
    │   └── vda5050.md
    ├── 50-physical-ai/    # Physical AI:模擬與 sim-to-real
    │   ├── README.md
    │   ├── claude-physical-ai-workflow.md
    │   ├── gazebo-slam-warehouse.md
    │   ├── gpu-lidar-how-it-works.md
    │   ├── isaac-sim-isaac-lab-amr.md
    │   ├── physical-ai-overview.md
    │   ├── project-forklift-rmf-gazebo.md
    │   ├── sdf-3d-models.md
    │   ├── sensor-data-and-3d-reconstruction.md
    │   ├── sim-to-real.md
    │   ├── simulation-asset-sources.md
    │   └── simulation-gazebo-ros2.md
    ├── 55-vlm-llm/        # VLM 與 LLM
    │   ├── README.md
    │   ├── llm-vlm-for-robots.md
    │   └── local-llm-on-nvidia-gb10.md
    ├── 60-compliance/     # 法規與認證
    │   ├── README.md
    │   ├── battery-certification.md
    │   ├── pwc-semi-iso3691-certification.md
    │   └── semiconductor-amr-standards.md
    ├── 70-security/       # 資安
    │   ├── README.md
    │   ├── ota-firmware-signing.md
    │   ├── secure-boot.md
    │   └── sros2-dds-security.md
    ├── 90-foundations/    # 數學與力學基礎
    │   ├── feedback-control-pid-lqr.md
    │   ├── gaussian-from-first-principles.md
    │   └── robot-dynamics.md
    ├── _meta/             # 工作方法與教訓
    │   ├── github-actions-gz-sim-playbook.md
    │   └── lessons-learned.md
    ├── _refs/             # 參考論文導讀
    │   └── nav2-survey.md
    └── _legacy/           # 舊版單檔整理(已被取代,保留對照)
        ├── README.md
        ├── delivery-robot-architecture.md
        └── delivery-robot-fundamentals.md

兩層骨幹:10-core/ 是換了形態也還在的部分(硬體 / 韌體 / 導航),20-forms/ 是換了形態就得換的部分。判準是「把形態換掉,這篇還成不成立?」

數字前綴是為了讓 GitHub 的字母排序剛好等於閱讀順序(沒有前綴的話 core/ 會排到 90-foundations 後面)。每個 doc 開頭一段「一句話定位 + 延伸閱讀連結」;每一區都有 README.md 當入口。


分輪計畫與進度

輪次 主題 產出 狀態
R1 基礎建設 + 送餐機器人拆分 PLAN/README/CONTEXT;把既有架構與 28 節基礎原理拆成 hardware/firmware/navigation 主題檔;Physical AI 總覽 ✅ 完成
R1.5 審查修補 章節對照表 section-map.md、README 加 30 秒總覽+核心詞、進階小節標示、文字修正;Physical AI 新增「感測器資料與 3D Gaussian 重建」(含高斯為何無所不在) ✅ 完成
R3 主板控制與模擬 board-simulation-renode.md(STM32/Arduino 在電腦上跑 Renode 模擬)+ 2 張第一性原理 SVG ✅ 完成
R4 導航數學 kinematics-and-coordinate-transforms.md(座標轉換/TF)、path-planning.md(Nav2 規劃)+ 4 張第一性原理 SVG ✅ 完成
R5 Physical AI 模擬 isaac-sim-isaac-lab-amr.mdsimulation-gazebo-ros2.mdsim-to-real.mdclaude-physical-ai-workflow.md;高斯第一性原理 + 一批數學/流程 SVG 示意圖 ✅ 完成
R2 多機調度軟體 open-rmf.mdvda5050.md(OpenRMF 如何透過 VDA5050 調度不同廠家機器人)+ 4 張第一性原理 SVG ✅ 完成
R6 圖文並茂 把既有 ASCII 圖逐步升級成 SVG;數學概念一律配圖(已起步) 🔄 進行中
R7 第一性原理補強 核心公式(差速/odometry/FOC/AMCL…)從根本推導 + 7 張數學 SVG ✅ 完成
R8 法規與認證 電池認證(UL 2271/2580、LFP)、半導體 fab AMR(SEMI S2/E84) ✅ 完成
R11 路網規劃與交管 + 全 repo ASCII→SVG 40-fleet/roadnet-and-traffic-control.md(三條技術路線第一性原理比較:空間表示、衝突偵測、仲裁脫困;前導線公式推導、柵格化理由、環形鎖 DFS)、40-fleet/indoor-amr-roadnet-selection.md(叉車/搬運車/送貨機器人分場景選型)+ 6 張 SVG;既有硬體/導航文件的 ASCII 概念圖批次升級 SVG;README 重編(加全書地圖、補回漏索引的資安三篇);經專家(技術正確性)+ 學生(可讀性)審查並修補(R11.5:AprilTag 斜看方向鏡像、Clarke α 軸對齊 a 軸、前導線圖文編號統一、地標算例自洽化、I²t 疊純 I²t 參考線、補 base_link/Nav2/MAPF/潛伏頂升的首次出現解釋) ✅ 完成
R10 VLM & LLM + 本地 AI 硬體 55-vlm-llm/llm-vlm-for-robots.md(LLM/VLM/VLA 第一性原理)、local-llm-on-nvidia-gb10.md(FLOP 量級+記憶體頻寬 bound+量化+GB10/DGX Spark 官方規格查證+本地部署)+ 7 張第一性原理 SVG;經專家(技術正確性)+ 學生(可讀性)審查並修補(FP4→FP16 換算修正、prefill/batching/KV cache 限定、補 self-attention QKV 圖等) ✅ 完成

輪次可調整;新需求隨時插入。已寫好的檔不重做,只增修。


每輪收尾固定流程

  1. 更新受影響的 README.md 索引與本檔進度表。
  2. git add → commit(繁中 message)→ push 到 origin/main
  3. 啟動兩個 review agent 讀新增/修改的文件:
    • 專家角色:檢查技術正確性、有無過度簡化或錯誤、領域用詞是否精準。
    • 學生角色(硬體不熟的讀者):檢查是否讀得懂、哪裡卡住、需要補什麼前置知識或圖。
  4. 把兩方意見整理成下一輪的修訂清單。

審查待辦 backlog(R1 專家/學生審查產出)

來自 R1 收尾的兩個 review agent,尚未處理的高優先項,排進後續輪次:

R13 路徑平滑與軌跡生成 30-navigation/path-smoothing-and-trajectory.md:從「折線轉角 κ→∞」推起,涵蓋幾何/時間的拆分、G0–G3 連續性階梯、Bézier 完整推導(Bernstein 基底→凸包性質→de Casteljau 碰撞檢查→曲率式)、B-spline(Cox–de Boor、局部支撐、內建 C²)、NURBS、clothoid、離散平滑器最佳化、速度規劃(梯形 vs S 曲線七段、彎道速度上限),以及 Open-RMF 兩 waypoint 間三次 Hermite 與 Bézier 互轉 + 6 張 SVG;順帶修掉 nav2-survey「IV 路徑平滑」指向沒有該節的檔案這個斷鏈 ✅ 完成
R14 模擬資產來源盤點 50-physical-ai/simulation-asset-sources.md:先拆清「找 3D 模型」其實指五類東西(機器人本體/場景/物件/材質/訓練環境),再依生態盤點來源並實查數字(Fuel 3360 models/270 worlds、forklift 只有 1;AWS RoboMaker 服務 2025-09-10 終止、五個 world repo 全數封存;rmf_demos 七個場景;Isaac 雲端 asset root 可只抓單檔核對 prim 路徑),最後用 visual/collision/inertial/語意標註 四欄說明「拿到資產不等於能用」與 SimReady 的價值 + 1 張來源地圖 SVG;順帶修掉 sdf-3d-models.md 引用的 app.gazebosim.org/fuel 死連結(實測 404) ✅ 完成
R14.1 資產來源的網址與 repo 實測 補上 §5/§6 原本缺的入口連結,並新增 §9.1 網址狀態表(18 條全數 200)與 §9.2 GitHub repo 表(14 個,含 ★/最後 push/封存/授權)。實測三件會誤導人的事:Isaac 雲端 asset root 4.5/5.0/5.1/6.0 都在(Nova_Carter_ROS.usd 各 85,526 / 135,278 / 151,435 / 153,649 bytes,可不裝 Isaac Sim 就核對 USD 結構);Asset Browser 文件的 latest6.0.0 路徑實測 404(6.0 搬過位置,改認版本號);allenai/procthor 最後 push 停在 2023-04-07、StanfordVL/OmniGibson 無授權標示。另記下自己踩到的 jq 陷阱(--jq '.archived and "已封存" or "活躍"' 恆為 true,因 jq 的 and/or 回傳布林而非運算元)並寫進 §9.3 ✅ 完成
R15 補完 R12 中斷的圖 + R11 backlog R12 那五張沒把關的 SVG 逐一渲染核對:法規編號全部對得上原文(S2/S8/S14/S22、E84/E87/E88/E90/E10、ISO 3691-4/13849/14644、UL 2271/2580、UN 38.3、CISPR/CNS 13438、IEC 62368-1),沒有臆造;修掉 pai-reality-gappai-gap-techniques 底部各數十 px 的空白 viewBox 與兩處標籤壓線後插進對應各篇。新畫五張:cmp-certification-roles(取代 pwc 篇那張 38 行的 ASCII 流程圖)、pai-isaac-stackpai-isaac-ros2-nav2meta-ci-verification-ladderroadnet-two-layer。順帶修掉兩個內容問題:pwc-semi-iso3691-certification.md 標題寫「三種認證角色」但表格是四種(已改四種);同檔 §5 出現兩個內部專案代號(已改成中性描述) ✅ 完成
R15.1 視覺與體例一致性掃全 repo 派便宜 agent 盤點 63 個 md + 174 張 SVG,主迴圈逐條核實後修:八張圖底部空白 41–80 px 裁到一致的 18 px 餘裕;三張圖右側內容被 viewBox 裁掉(max-entropy 圖例少 63 px、indoor-amr-decision 那段字超出自己的框 69 px、amcl-multimodal 少 21 px);字體字串統一(rviz-slam-mapping 多插了 DejaVu Sans);三張縮到 0.71–0.74 倍的圖放大回 0.9 倍附近;sensors.md 三張 1280×1600 截圖與 localization.md 的 AprilTag 圖從裸 ![]() 改成置中 + 尺寸控制;pwc-semi-iso3691 整篇全形標點(153 個)轉半形。另把跨檔 §N 改成可點連結(51 處 / 10 個檔),同檔內部維持裸寫 ✅ 完成
R15.2 套用專家 + 學生審查 專家沒抓到必須修的技術錯(標準編號與 Isaac/Nav2 事實逐一比對官方來源都對得上),但學生抓到一個更嚴重的:img/keenon_t10.png 標成「DINERBOT T10 官網頁面」,實際是 Keenon 官網首頁、主視覺是 KLEENBOT C40 掃地機——而且這個假宣稱是 R15 把裸 ![]() 改成置中寫法時我自己「補完」出來的(原本 alt 誠實寫「Keenon 官網首頁」)。三張截圖在 height="240" 下只有 192 px 寬、根本讀不到規格,整段拿掉。另修:pai-gap-techniques 的三個等大方框被讀成「三選一」(加 ①②③ 與接力順序帶)、pai-isaac-stack 回頭箭頭只有一條卻標「改設計 / 換 reward」(拆兩條)、cmp-semi-standards-map 的向下箭頭被讀成檢查順序(補方向提示);精確度:CNS 13438 對應 CISPR 22 而非 32、ISO 13482 是個人照護機器人不是服務機器人、清掉一處可辨識的客戶指涉;補 PL/SIL/SELV/GAN/FID/SSIM/PSNR 的當場翻譯;標明 sim-to-real「五個來源」是本篇二次加工非論文原始分類 ✅ 完成

教訓:改寫既有內容時,不要「順手補完」自己沒查證的細節

R15.2 那個假宣稱值得記住。原本的圖說是誠實的「Keenon 官網首頁」,我在做「裸 ![]() → 置中寫法」這個純格式的改動時,覺得 alt 文字寫得太籠統,就順手改成「Keenon DINERBOT T10 官網頁面」——內容我沒開圖看過。格式改動裡夾帶未查證的內容改動,而且因為 commit 訊息寫的是「改排版」,審查時也不會有人特別去看它。

規則:格式改動就只改格式。 覺得原本的描述不夠好,那是另一件事,要另外查證再改。

量測方法備忘(下次要再掃時直接用)

SVG 的「內容到底畫到哪」不能用抓 y=/x= 屬性的座標估法——量不到 <path>文字實際渲染出來的墨水範圍,估出來的數字是錯的。正確作法是用 chrome 跑 getBoundingClientRect() 再換算回 viewBox 座標(腳本邏輯見 R15.1 的 commit 訊息)。

getBBox() 也不行:它回傳套用 transform 之前的框,有 rotate 的標籤會被誤報成溢出(pai-isaac-stackmeta-ci-verification-ladder 都被這樣誤標過)。

R16 擴大範圍到多形態 + 移動操作第一輪 使用者指出機器人不限服務型,人形 / 四足 / 搬運車加手臂都算。先重構成「共通核心 + 形態分支」(判準:把形態換掉這篇還成不成立),10-hardware/20-firmware/30-navigation 整批進 docs/10-core/,只有 chassis-and-drivetrain.md 真的搬去 docs/20-forms/wheeled-amr/;177 個圖引用與所有 md 連結逐一改寫並驗過零斷鏈。再寫第一種形態:移動操作——arm-kinematics.md(FK 求值 vs IK 求根、DH 的 4 個參數是兩個約束消出來的、六軸八組解、球型手腕是機構遷就 Pieper 準則、Jacobian 三重身分含虛功原理推 τ = JᵀF)+ mobile-manipulation.md(冗餘與零空間投影、三種協調策略、公分級定位對公釐級抓取的誤差預算、合力作用線與傾覆)+ 9 張新 SVG。README 改成多形態定位 ✅ 完成

這一輪查證抓到的兩件事

ISO/TS 15066 是否已正式撤銷:公開來源說法不一致,只能確定技術內容已進 ISO 10218:2025 正式條文。文件裡已標明不要對客戶說「TS 15066 已廢止」。

R17 形態第二輪:四足 20-forms/legged/ 兩篇 + 8 張 SVG。legged-fundamentals.md 從一個觀察推起:翻遍一隻四足找不到任何一顆馬達連到軀幹——於是軀幹 6 DOF 沒有直接控制輸入(欠致動,永遠差 6 個);接觸集合 16 種讓系統變成混合系統(沒有一組固定增益能同時對 16 種動力學都好);支撐多邊形從三角形退化到線段再到不存在,靜態判準不是難滿足是失去意義;ZMP 管腳與地的介面、capture point 管能量餘裕;狀態估計的水平位置與 yaw 在數學上不可觀測gait-and-actuation.md:duty factor 的門檻、腳每步撞地讓工業減速機不能用、QDD 與 SEA 是「衝擊被誰吸收」的兩種答案、RL 為什麼主導、安全標準目前是空的 ✅ 完成
R17.1 套用 R17 審查:兩個錯誤斷言 學生與專家各自獨立抓到同一個錯:「duty factor < 0.5 必有飛行相」被我寫成「幾何上的必然」。實際門檻是 1/n(n = 獨立錯開的支撐組數):四腳各自錯開 0.25、對角配對(trot)與雙足才 0.5;四腳平均錯開要 d ≥ 3/4 才恆三腳著地。專家補上真實反例 amble(靈長類、大象,duty factor < 0.5 卻無騰空相,Schmitt 2006 JEB 209:2042)。專家另外抓到我沒發現的第二個錯:capture point 被解釋成「動能被抬升重心的位能吃光」,但 Pratt 2006 / Caron 用的是定高倒單擺,高度不變、沒有位能可吃——改成完整推導(ξ = x + ẋ/ωξ̇ = ω(ξ−p) → 踩在 ξ 上發散項歸零、指數收斂)。另補:ZMP「合法但仍會跌倒」的機制(瞬時條件,合法的是每一格不是整段軌跡)、img/nav-roll-pitch-yaw.svg + 定義表(全庫二十幾個檔在用卻從沒定義過)、諧波減速機一句話說明、反射慣量為何是平方的能量推導、接觸集合 16 是組合上限 ✅ 完成
R17.2 覆審修正輪(學生 + 專家) 修正本身也被抓到錯。 專家指出 duty factor 0.5 對四足不是「統計性描述」——Hildebrand 的對稱步態定義就是同一對左右腳差半週期,所以每一對是 n=2、k=1 的系統,d ≥ 0.5 ⟹ 無騰空相 是成立的幾何定理。真正的病是把充分條件當成充要(反向的 d < 0.5 ⟹ 有騰空相 才錯)。上一輪把病因診斷成「把統計說法升級成幾何必然」並已寫進 lessons-learned,等於把錯誤診斷制度化,一併改掉。另修:amble 引用漏掉來源限定詞「至少一肢 duty factor < 50%」+ diagonality 區間;nav-roll-pitch-yaw.svg 的 roll 畫反(正 roll 是左側抬起,後視圖上是螢幕順時針);「不可反向驅動是高反射慣量造成的」錯——反射慣量是純運動學量,自鎖來自摩擦與反向效率 η_rev ≈ 2 − 1/η_fwd,改成兩個彼此獨立的性質;反射慣量「兩個 N」改用力矩路徑;諧波減速機補波發生器;ZMP「式子裡沒有速度」限縮到點質量形式;補與 Pratt 原文 orbital energy 的對帳;3/4 門檻補 McGhee & Frank 1968。學生端:撤回的舊斷言還活在四處(兩處在 README 索引);capture point 補上三根缺的接線(方程式來源、ξ 的動機、p 就是壓力中心)+ 新圖 leg-capture-point-modes.svg;duty factor 兩張表收斂成 d ≥ k/n 一條規則 + 兩個但書(「等間隔」不能省、「至少 k 組」不是「恆為 k 組」);GitHub lazy continuation 把整段併進條列項 ✅ 完成

R17 查證抓到的四件事

  1. 足式的安全標準是空白,而且是被明確排除的。 ISO 3691-4 明訂不適用於具主動控制穩定性的機器人;ISO 10218 不管移動;ISO 13482 限非工業場域。制定中的 ISO/CD 25785-1(動態穩定工業移動機器人)範疇寫著「需主動控制才能維持平衡、斷電即可能失穩」,正是為此而開,但仍在草案(時程只查到「2026–2027」區間)。
  2. teacher-student 特權學習只能歸給 Lee 2020 → Miki 2022 這一支。 Hwangbo 2019 的核心是致動器網路、Rudin 2021 是訓練基礎設施,查不到它們也用同一框架的依據——不要把四篇說成同一套路線。
  3. 「zero-moment point」這個詞是 1970–72 才創的,Vukobratović & Juričić 1969 那篇原始論文並沒有用這個名字。
  4. Kenneally 那篇直驅足式論文是賓州大學的 Minitaur,不是 MIT Cheetah 系列——我在派工 prompt 裡把它歸錯了,研究 agent 抓出來並更正。

另記:「機身高度會漂」這個現象沒有公認的專有名詞,文獻都是描述性寫法。研究 agent 明確提醒不要杜撰一個聽起來像術語的稱呼——已照辦。

R17 這條線上抓到的三件事(每一件都是下一輪才浮出來的)

  1. 把充分條件當成充要。 d ≥ 0.5 ⟹ 無騰空相 成立(對稱步態每一對是 n=2 系統),反過來不成立(amble)。原文寫成雙向。判斷法:寫下「⟺」「必然」「才可能」之前,把箭頭兩個方向分開各證一次——正向證得出來會給人「整條都懂了」的錯覺。
  2. 解釋機制比寫對公式更容易錯,也更難被抓到。 capture point 的公式沒寫錯,但配上的物理解釋(動能換位能)跟模型假設(定高)直接矛盾,也跟自己引的兩份來源矛盾。「能量守恆」這類解釋最危險,因為讀起來太順。
  3. 修正本身也要被審,而且錯誤的診斷比沒有診斷更糟。 R17.1 把第 1 條的病因診斷成「把統計說法升級成幾何必然」,那是錯的,而它已經被寫進 lessons-learned.md 當成規則。派覆審的專家去讀「修正後的版本」而不是只讀原版,是這一次抓到的關鍵。

三件事全是審查抓的,沒有一件是自己複查抓的。順序也有訊息:學生問「憑什麼」先到(「照 walk 那張圖的排法算,門檻是 0.25」),專家答「對照哪一篇」在後,而第三件要等到下一輪覆審才浮出來。角色分開派 + 修正後再審一次,兩件都有效。

另記一個自己的推導失誤:roll 的旋轉方向我親手推過一次還推錯——逆時針是把 9 點鐘帶到 6 點鐘(壓下去),不是抬起來。推導過不等於推對了,幾何方向這種一步就能翻的東西要用代數驗,不要靠腦內轉圖。

R18 機器人動力學 90-foundations/robot-dynamics.md:整合 HITSZ-OpenAuto AUTO3005(港科大李澤湘 2012 講義 + MLS 教材)的動力學章。從「速度環為什麼把動力學藏得住」推起:Newton vs Lagrange 兩條路(單擺對照,約束力不做虛功)、廣義座標、慣性張量與剛體動能、M(θ)θ̈+C θ̇+N=τ 三項各自的來源(C = 慣量隨構型變的倒影,Christoffel)、平面二連桿的 m₁₁=α+2βcosθ₂、三條結構性質(M 正定 / Ṁ−2C 反對稱=能量記帳 / 對慣性參數線性)、Newton-Euler O(n) 遞迴(重力=基座向上加速的技巧)、完整 vs 非完整約束(差速側滑約束積不回去→接回 Hybrid-A* 與曲率約束)、computed torque 與 PD+重力補償的 Lyapunov 能量論證、「什麼時候可以不管動力學」的兜底機制表 + 7 張 SVG(全部 chrome 渲染核對過)。體系註記:原課程用旋量/PoE,本篇用廣義座標寫法銜接全書 ✅ 完成
R18.1 套用 R18 專家 + 學生審查 專家抓到五處「詮釋句比數學多說半步」:「C 不做功」是過強斷言(θ̇ᵀCθ̇ 一般非零,為零的是它與 ½Ṁθ̇ 的組合→改成「能量帳上淨貢獻為零」,CONTEXT 同步改);P3 的線性參數化指錯對象(對 (m, c, ℐ_c) 不線性,線性的是 (m, m·c, 對連桿原點的 ℐ) 這組;補 base parameters 但書);質心「唯一選擇」加「對任意運動」限定(固定點特例也行);「非完整=不限制能到哪」限縮到差速車單約束例(一般要可控性論證);QDD「沒有平方放大」改成「只剩幾十倍」。Coriolis 圖右半 2m·θ̇ᵢθ̇ⱼ 量綱不是力→改 2m·ṙ·θ̇ᵢ。學生端 18 條:∂L/∂θ̇ 把 θ 與 θ̇ 當獨立引數 + τ 是廣義力放右邊(兩個最大裂縫)、P2 補「Mθ̈ 已用運動方程代換」與反對稱定義、帶約束完整方程 + λ 命名 + Aᵀλ 形狀從虛功原理接回、ω 是 3 維向量、q vs θ 符號交代、構型定義、Coriolis 圖與 2R 的對應註記、陀螺項 ω×ℐω 一句解釋、π 與圓周率消歧、hat 記號、正定⇒可逆白話、極點改白話、科氏/達朗貝爾/克里斯多福/自適應/李亞普諾夫/全身控制/摩擦錐/前饋當場翻譯、§8→§9 接橋;剛體動能圖改成「同一根棒兩種擺法」與正文對齊、單擺結論式字級加大 ✅ 完成
R19 GitHub Pages 上線 https://wicanr2.github.io/robot-notes/ 。_config.yml 用 GH Pages 白名單 plugin(optional-front-matter / readme-index / relative-links / default-layout / titles-from-headings)讓純 markdown repo 直接成站,docs/_legacy_meta_refs 底線目錄明確 include 否則被 Jekyll 吃掉;_layouts/default.html 單檔版面(層級靠細線與留白、關鍵色只有墨綠一個、表格細線無彩色表頭、中文行高 1.95、深色模式同一組語意變數換值)。數學式:kramdown 在 GH Pages 實際輸出裸 \[...\],MathJax 3 的 displayMath delimiter 直接吃(另留 math/tex script 轉換 shim 當備援)。踩到一個:CSS img{height:auto} 會蓋掉 HTML 的 height 屬性,README 兩張 height="180" 產品照被撐成全寬——改成只對帶 width 屬性的圖做 height:auto。首頁與動力學頁(含 §2–§5 公式段)已實際 chrome 渲染核對。(這一輪的 include 寫法其實從未生效、關鍵色與版面已在 R23 換掉,見 R23) ✅ 完成
R20 回授控制:PID 與 LQR(叉車 / 搬運車) 90-foundations/feedback-control-pid-lqr.md,兩半各半。Part A 數學:從「開環要求映射完全已知且不變」推出回授的價值是「不需要準」;PID 三項逐項問「不加它缺什麼」,I 項給到內模原理這一層(常值擾動的生成模型是 1/s → 迴路必須有積分器;斜坡需要兩個,所以貨叉等速上升用 PID 會留固定落差)、反算式 anti-windup、微分踢與濾波微分、離散化三個會出事的細節;xᵀQx + uᵀRu 用 Taylor 展開逼出來(前兩項被「目標點為零」與「原點是最小」強制歸零 → 最低階非零項就是二次項),R 為何必須嚴格正定、Q/R 只有比值有意義、Bryson 法則;u = −Kx動態規劃 → HJB → 猜 V=xᵀPx → 對 u 求導完整推出(不是假設的結構,是推導的結果),CARE 與 DARE 兩版都推;可控性(只算到 A^{n-1}B 是 Cayley–Hamilton)、Lyapunov 證閉迴路穩定(V̇ = −(xᵀQx+uᵀRu),下降速率等於當下正在付的代價)、裕度保證與它的四個失效條件。Part B 叉車:舵輪 ICR 推 ω = v·tanδ/L、非完整約束;四層迴路(路徑追蹤 LQR / 轉向速度 PID / FOC PI / 貨叉位置環)與「什麼時候該從 PID 換成 LQR」的三條判準;標準 LQR 沒有積分器在坡道會留穩態偏差 → LQI;橫向與航向誤差為何不能拆成兩個 PID(B = [0, v/L]ᵀ 的那個零);載重增益排程;LQR 的三個假設叉車違反三個 → MPC(並指出 LQR 是 MPC 的特例、MPC 終端代價的 P 就用 LQR 的 Riccati 解);可執行的 Python 算 K 與 C 的 MCU 實作。11 張 SVG,全部 chrome 量測邊界 + 抽三張渲染核對 ✅ 完成

R20 這一輪抓到的四件事

  1. 推出了一個文獻沒有的結論,而它必須標明是自己推的。 三輪平衡重式叉車是後輪轉向、前軸驅動,順著無側滑約束算下去,後軸中心對轉向輸入的傳遞函數是 v(Ls−v)/(Ls²)——零點在 s = v/L,前進時落在右半平面,所以車尾會先往錯的方向走,而且閉迴路頻寬被硬性限制在 v/L 的量級。倒車時 v < 0,零點移到左半平面,限制消失。這同時給了「叉車載重常倒著開」一個控制論上的解釋——但文獻與原廠訓練資料講的理由是視野與載重分配,查不到有人把最小相位當成理由。正文已標明這是本篇的推導、不是既有論述。
  2. 圖的分類標籤要對得上實體,不是對得上數學模型。 第一版的舵輪 ICR 圖把「轉向輪在前」那半標成前移式 / 電動拖板車——但 reach truck 的舵輪在遠離貨叉那端,貨叉朝前行駛時它是後輪轉向,落在圖的另一半。數學模型沒錯(tricycle 就是 tricycle),錯的是把它掛到哪台車上。改成以「行進方向」為準的標題後才自洽,而且正好把倒車那一節的伏筆埋進圖裡。渲染核對抓到的,量測抓不到這種。
  3. 研究 agent 對叉車構型的描述自相矛盾,而既有文件是對的。 agent 回報「三輪平衡重式:後方單一舵輪(驅動+轉向同一輪),前方兩個驅動輪不轉向」——後輪既驅動又轉向、前輪也驅動,自己打自己。project-forklift-rmf-gazebo.md §3.1 早就查證過(標明來源 Toyota/Raymond/Hyster):前兩輪驅動、後單輪主動轉向。採信既有文件,並在本篇連回去,沒有重新裁定。
  4. 邊界量測與重疊檢查抓的是不同的病,兩個都要做。 getBoundingClientRect 換算回 viewBox 抓到一處真溢出(標籤超出右緣 8 px)與六處邊界過緊 / 留白過寬,但完全抓不到標籤壓在曲線上——那三處是渲染成 PNG 後看出來的(I 與 P 兩個標籤疊字、D 的切線與曲線重合到分不出來、P+I 的說明壓在藍色曲線上)。

待查證(正文 §15 已列):各機型舵輪的轉向角範圍、ISO 2328 / 2331 各級叉齒尺寸(所以正文只寫「扣掉厚度後剩幾十毫米」不給精確餘裕)、ISO 3691-4 的具體速度與停止距離(標準原文付費未購買)、Balyo / Seegrid / Fox Robotics 的官方定位精度、叉車領域明確以 gain scheduling 命名的公開文獻(查不到,正文標明是把通用理論套上去的推導)、Apollo lat_controller.cc 現行原始碼(取用路徑回 404,狀態向量定義來自二手來源)。

R20.1 套用 R20 專家 + 學生審查 專家抓到一個必修:單輸入 LQR 的增益裕度 (1/2,∞) 與相位裕度 60° 應引 Kalman 1964(When Is a Linear Control System Optimal?, ASME J. Basic Eng. 86(1) 51–60,已實查 DOI 10.1115/1.3653115;該文核心結論「回歸差絕對值在所有頻率上 ≥ 1」正是裕度的來源),原本引的 Safonov & Athans 1977 標題明寫 multiloop,拿它支持單輸入結果是錯位。另補三處限定:§2.2 貨叉斜坡的積分器數量、§12.2 MPC 穩定性還需要終端不變集(只講終端代價是漏一半)、§4.1 二次型論證要 C² 而非只要可微。學生抓到全文最大的裂縫:拉氏轉換從頭到尾沒解釋,而 §10.2 整段 RHP 零點的推導建立在它上面——學生的原話是那段「讀了等於沒讀」,補了一張三列對照表(微分↔乘 s、積分↔除 s)與轉移函數/零點極點的一句話定位。另補三處無聲跳步:矩陣對向量求導的兩條規則、「純量等於自己的轉置」這個技巧(§5.3 與 §6.2 各用一次卻從沒交代)、§6.2 的 Lyapunov 代入原本五步一次跳到底(現在逐項展開 ①②③)。以及 Q^{1/2}、正定、嚴格凸、頻寬、相位裕度、QP、T_tN 的當場翻譯,ω 角頻率與角速度雙重用法的標註,舵輪圖移到 ICR 被定義之後。新增第 12 張圖 ctl-forklift-stability-triangle,並把 §11.1 從一句話擴成傾覆力矩推導:m·a·h > m·g·d ⟹ a_max = g·d/h,配 a = v²/Rv_max = √(g·d·R/h)——質量兩邊約掉,決定翻不翻的是幾何不是載重 ✅ 完成

R20.1 抓到的三件事

  1. 審查 agent 的診斷要自己驗算,它可能只對一半。 專家對引用的指控成立,但它附帶的推論「Safonov & Athans 1977 已被 Doyle 1978 反駁」是錯的——1977 講的是狀態回授 regulator 的多迴路裕度,1978 講的是含 Kalman 濾波器的 LQG,兩者對象不同、並不衝突。照抄那個推論會在文件裡種下一個新的假斷言。最後只採納「引用錯位」這一半,把 Safonov 保留為多變量推廣並註明它處理的是狀態回授。
  2. 它確認對的那一行旁邊,才是真正錯的那一行。 專家指出 §13.1 的 Ad = I + A*T 對這個 A(A² = 0)是精確值不是近似——正確,而且是個好教學點。但同一段裡 Bd = B*T 才是錯的:精確的零階保持是 Bd = (T·I + T²A/2)·B,漏掉 T²/2·ABK 的第二個元素偏掉 2.2%(10.395 → 10.168)。專家沒抓到。是自己按著它的提示往下驗算才發現的——驗證一個斷言時,順手把它的鄰居也算一遍
  3. 選視角本身就是物理判斷。 穩定三角形圖的第一版畫成側視圖,渲染出來才發現 d(重心到傾覆軸的水平距離)幾乎變成 0——因為側視圖表達的是前後傾覆,而 §11.1 講的轉彎傾覆是側向的,要用後視圖才畫得出來。公式沒寫錯,錯的是用一個看不到該現象的視角去畫它。這和 R20 那條「圖的分類標籤要對得上實體」是同一類病的兩種形狀。

另記一個學生的判準值得留著:它讀完之後被要求用自己的話回答三個問題,「為什麼是二次型」答得完整、「K 從哪來」答得出來源但答不出每一步、「倒車為什麼好控制」只能複述而無法解釋機制。答不出來的那兩題,精確對應到文中真正缺的兩塊(矩陣微積分、頻域直覺)。比起請它列出「哪裡看不懂」,請它複述更能定位裂縫。

R21 取樣式 MPC:MPPI 的完整推導與 Nav2 實作 起因是「ROS 2 有沒有官方的 LQR / MPC」這個提問。查證結論:官方零 LQR(ros2_controllers 十幾個 controller、control_toolbox、Nav2 的五個 plugin 都沒有),唯一與 MPC 相關的是 nav2_mppi_controller,而它是取樣式不是解 QP 的。於是在 feedback-control-pid-lqr.md 補上 §13(原 §13–16 順推為 §14–17):Gibbs 變分原理自己推(最小化 E_q[S] + λ·KL(q‖p),把泛函湊成 λ·KL(q‖q*) − λ log Z,靠 KL 非負直接逼出 q* ∝ e^{−S/λ}p——指數權重不是設計選擇是推導結果,地位等同 §5 的 u = −Kx);重要性取樣讓算不出來的 Z 在分子分母對消,得到 softmax 權重;更新律的兩種等價寫法(論文的 u ← u + Σw_kε_k 與 Nav2 原始碼的 u = Σw_k v_k,因 Σw_k = 1 而等價);λ 溫度的兩個極端;核心那一節——整條推導裡 S 只出現在 e^{−S/λ},從頭到尾沒有求導,所以代價可以是 costmap 查表、碰撞布林、if-else,而 LQR 的閉式解正是用「代價必須是二次型」換來的;Nav2 實際參數(原始碼級核對)與 11 個 critic;PID / LQR / MPPI 三者對「代價需要多少結構」的光譜對照。新增 3 張 SVG(ctl-quadratic-vs-costmap 二次碗 vs 真實代價地形、ctl-mppi-mechanism 七步流程 + 軌跡束、以及順手修準的局部最小標記) ✅ 完成

R21 查證抓到的四件事

  1. 先 grep 自己的庫,答案就在裡面。 要回答「Nav2 為什麼不做 LQR」時,第一步不是上網搜,而是 grep docs/_refs/ ——那裡躺著 Nav2 維護者親寫的 survey 全文 PDFpdftotext 抽出來一 grep:全文零次提及 LQR。這個負面證據兩秒就拿到,而且比任何二手討論權威。它的 Table II(各 controller 的 Max. Frequency:MPPI 125 Hz、Graceful 1800 Hz、RPP >4000 Hz)與五類分法(reactive / predictive / geometric / machine-learning / control-law)也直接給出了「LQR 會落在哪一格、那格已經被誰佔住」的答案。
  2. agent 的引文要回原文核對,因為格式標記會在轉述中丟失。 研究 agent 正確找到了 navigation2#1710 裡 Macenski 對 LQR 的定性,但回報的純文字裡看不出那一行帶刪除線(~LQR/iLQR/CiLQR …~ MPPI supersedes)。刪除線正是「評估過、決定不做」與「還沒排到」的分野——用 gh api 讀原始 markdown 才看得到。
  3. 文件與原始碼不一致時,以原始碼為準,而且要主動去核對。 agent 自己誠實標了「參數預設值只是文件層級,建議另做原始碼級核對」。照做之後:預設值全部吻合(batch_size 1000、time_steps 56、model_dt 0.05、temperature 0.3、gamma 0.015),但Savitzky-Golay 濾波器在文件裡不明顯、原始碼確實有呼叫(optimizer.cppsavitskyGolayFilter)。這種只有讀碼才看得到的東西,正是筆記該寫進去的。
  4. 拿不到原文時,能自己推的就自己推,不要引用沒核對過的式號。 論文 PDF 抓不到(判定為掃描影像),agent 給的自由能式子是經 HTML 轉譯後的摘要,而且不同文獻的定義差一個 −λ 因子。處置是自己重推一次 Gibbs 變分原理——只用 KL 散度非負這一個性質,四行就推完,結論自洽且與文獻一致。正文標明這是本篇自推、未逐式核對原文,並註記那個因子差異不影響 q* 的形式。
R21.1 套用 R21 專家 + 學生審查 專家把 §13 的數學逐條重推,核心推導全數驗算通過(Gibbs 變分、重要性取樣的 Z 對消、兩種更新律等價、λ 的兩個極限、Ackermann 的 \|ω\|≤\|v\|/R_min 與 §7.1 κ=tanδ/L 等價);抓到四處要補:§13.2 缺兩個技術前提(q≪pZ<∞)、QP 與 NLP 被揉成一列(QP 是二次代價+線性約束因此恆凸,「只要可微、允許非凸」講的是 NLP,兩種求解器的假設不同 → 拆成兩列)、§13.7 的「56,000 個位姿就是 125 Hz vs >4000 Hz 的來源」因果過度簡化(RPP 根本不模擬未來,運算性質不同,不能反推單位姿成本)、§13.1 的 p 每輪都用上一輪的解重新定義所以最優性是相對「這一輪的名目控制」、整條演算法是疊代近似而非一次求到全域最優。另補三條限制:有效樣本數塌陷、加權平均在非凸可行集下可能自己製造不可行解、維度與時域的覆蓋率詛咒。學生判定 §13.2 整段「讀了等於沒讀」,原因是三個斷點:S/λ = log e^{S/λ} 那步沒寫、「分母上下同乘 Z」的措辭誤導(實際是拿 Zq* = e^{−S/λ}p 做代換,不是通分)、以及KL 散度全文從沒被寫成公式卻被拿去對消算式。另補 E_q[·]、泛函、K、logit、歸一化常數的當場翻譯,並修掉 Σ 同時當共變異數與求和的符號衝突(改記 Σ_ε)。圖修兩處:MPPI 流程圖的 ⑥→⑦ 少一個箭頭讓流程看起來在⑥就結束、代價地形圖的「障礙物」只有文字沒有實體 ✅ 完成

R21.1 抓到的三件事

  1. 文字定義不能拿來對消算式。 KL 散度在 §13.2 之前只有一句文字描述(「衡量兩個分布差多少,恆非負」),然後推導裡直接把 E_q[log(q/q*)] 記成 D_KL(q‖q*)。對已經知道定義的人這是同義反覆,對不知道的人這是憑空跳步——學生的原話是「一個從沒被寫成算式的東西,被拿去對消一個算式」。規則:凡是會在推導中被當成算式操作的符號,就必須先以算式的形式出現過。
  2. 描述動作的措辭要對得上實際做的動作。 「分母上下同乘 Z」在數學上是錯的描述——實際做的是用 Zq* = e^{−S/λ}p 這個已知等式做代換。學生說這句話「誤導我去找一個乘法步驟」。這種錯專家抓不到(知道答案的人會自動腦補成正確操作),只有真的在跟著推的讀者會卡住。
  3. 專家與學生抓到的是不相交的兩組問題。 這一輪特別明顯:專家的四條全在「斷言精不精確」(QP vs NLP、因果簡化、缺前提、最優性的範圍),學生的四條全在「跟不跟得上」(缺中間步驟、缺公式定義、符號衝突、圖少一個箭頭)。兩組沒有任何重疊。 只派一邊,另一邊的問題會完整地留在文件裡。
R22 Nav2 外掛演算法完整參考 30-navigation/nav2-plugin-algorithms.md,把官方 configuration guide 左欄的 5 個 planner + 5 個 controller + 3 個 smoother + AMCL 逐一拆開,每個回答「解什麼問題 / 數學核心是什麼 / 哪幾個參數真的進得了公式」。開場先釘定位:四個角色各回答一個不同的問題、介面窄到只有一條 Path 所以每格都能單獨替換、以及為什麼 controller 也要避障(planner 那條路徑在算出來的那一刻就開始過期)。內容重點:NavFn 的波前傳播 + 梯度下降取路徑(位能用二次核而非距離);Theta* 的 line-of-sight 與 Lazy Theta*-P 變體;Hybrid-A* 的雙啟發式為何取 max(兩個各放寬一個約束 → 兩個下界 → max 仍可採納但更緊);State Lattice 的離線控制集;RPP 的 κ = 2y/L² 幾何推導 + 四層調節(其中障礙鄰近調節是從 costmap 值反推距離,即膨脹層代價函數的反函數,因此與膨脹層參數綁死);Graceful 的自我中心極座標閉式控制律(Park & Kuipers ICRA 2011,含 −1/r 為何造成「越近修得越用力」與 v_max·r/r_slowdown 如何消掉那個奇異點);DWB 的動態視窗與 10 個 critic;Rotation Shim 的兩個角度門檻;三個 smoother 是同一個目標函數的三種解法。4 張 SVG(四階段資料流、Hybrid-A* 雙啟發式、純追蹤幾何 + 四層調節、SG vs 移動平均)。依使用者指示「新篇當主」,path-planning.md 的兩張對照表改成指向新篇 ✅ 完成

R22 抓到的四件事

  1. 文件與原始碼的落差要主動找,而且它藏在最不起眼的地方。 AMCL 有兩種雷射模型,beam 是教科書的四項混合(z_hit/z_short/z_max/z_rand),但 Nav2 常用的 likelihood_field 只有 z_hitz_rand 兩項——z_shortz_max 在那個模型裡根本不存在。照著教科書調 z_short 卻用著 likelihood field,那個參數不會被讀到。這只有讀 likelihood_field_model.cpp 才看得見,官方文件沒有點出來。同一個檔案裡還有一行自承:逐光束的組合是 p += pz³ 這種經驗式(註解寫「works well though」),不是嚴謹的機率連乘。
  2. 「文件沒給的公式」有兩種,處理方式不同。 一種是原始碼裡有(Hybrid-A* 的 max 組合與 travel_cost 分段、Simple Smoother 的更新式、Graceful 的控制律、RPP 的四層調節)→ 讀碼補上並標明以原始碼為準;另一種是連原始碼都沒有現成式子的(Savitzky-Golay 的係數表)→ 自己算:window=7, poly=3 的係數是 (−2,3,6,7,6,3,−2)/21,並驗證了係數和為 1、三次以下完全保留、四次以上才平滑。第三種是兩邊都查不到的(Smac 2D 的啟發式、State Lattice 的代價組合、Constrained Smoother 的逐項解析式)→ 標待查證,不臆造
  3. 既有的筆記就是新篇的骨架,前提是先去找。 Simple Smoother 的原始碼更新式一看就眼熟,於是把它跟 path-smoothing-and-trajectory.md §6 的離散平滑器目標函數接了起來。⚠ 這個連結的數學推導在 R22.2 被專家推翻——它不是曲率能量的梯度下降,是一階長度能量的。正確版本見 R22.2 第 1 條。
  4. 全庫掃描比單篇驗證划算。 為了驗自己新寫的錨點做了一個掃描器,順手掃全庫,抓到 3 個既有斷鏈——而且它們和我當下踩的坑是同一條規則的兩個方向:GitHub 的錨點會移除標點、但把空格轉成連字號。所以標點兩側有沒有空格,決定了兩個詞是黏在一起(MPC:MPPImpcmppi,我踩的)還是留下連字號() — 用-用,那三個斷鏈踩的)。全庫 764 個內部連結現在全通。
R22.2 套用 Nav2 演算法篇的專家審查 專家逐項手算 + gh api 核對七個套件的原始碼與 declare_or_get_parameter 預設值。抓到一個實質錯誤(§4.1 Simple Smoother 的推導,見下)與一個只對一半的指控(§3.1 的 ln(253),見下)。其餘修正:§2.4 補上「放寬後的成本函數不得超過真實邊代價」這個必要前提,並指出 h_obstacle 其實是代價加權距離(疊了 cost_penalty)而非純幾何、h_distance 因為真實邊代價含 travel_distance_reward = 1 − retrospective_penalty(0.015)而嚴格說不再是精確下界(刻意用可採納性換搜尋速度);「啟發式越緊展開越少」補上 consistent + 固定 tie-breaking 的前提(Dechter & Pearl 1985)。§3.2 的奇異點歸因改正:r→0κ~C/r,曲率降速項是 O(r²)r/r_slowdownO(r),實際 binding 的是前者;若 binding 換成 √(2ra)O(√r)ω 反而發散——三項沒有一項能單獨保證有界。DWB 的 critic scale 誤標為預設:程式碼內建預設全是 1.0,32.0/0.02 是 TB3 範例值。另補 §2.6 的平滑時間差距、SG 高階成分是「衰減」非歸零、AMCL 的 laser_model_type 預設就是 likelihood_field(所以那個參數落差是開箱即用的行為)。專家另抽驗 15+ 項參數預設值,除 DWB critic 外全部相符 ✅ 完成

R22.2 抓到的兩件事

  1. 用自己的錯誤假設寫的驗算,驗不出那個假設是錯的。 R22 宣稱「Simple Smoother 的更新式正是曲率能量 Σ‖y_{i−1}−2y_i+y_{i+1}‖² 的梯度下降」,而且當時跑了驗算腳本自我確認。錯在哪:y_i 出現在三個相鄰的二階差分項裡(k = i−1, i, i+1),完整偏導是五點的重調和算子 (1,−4,6,−4,1),四階;我當時只取了「含 y_i 的主項」,而那個腳本裡寫的正是這個錯誤簡化,所以它當然「吻合」。真相是:三點更新式是一階長度能量 Σ‖y_{i+1}−y_i‖²精確梯度下降(對它取偏導得 2y_i − y_{i−1} − y_{i+1},取負號正好是原始碼那一行),而原始碼註解自己就寫著「Smooth based on local 3 point neighborhood」。 規則:當一個變數出現在多個項裡、而你只取其中一項時,那不是「取主項」的簡化,是換了一個不同階的算子。 「只取主項」這句話在推導裡出現,本身就該是警訊——寫下它的時候要停下來問「丟掉的那些項是同階的嗎」。
  2. 兩個 agent 給不同答案時,可能兩個都只對一半。 查證 agent 抄 RPP 原始碼給 ln(253),專家核對膨脹層給 252,而專家據此判定「文中誤植」。自己回頭讀兩邊原始碼才看到真相:RPP 確實寫 log(253.0f),而膨脹層的正向乘數確實是 (INSCRIBED_INFLATED_OBSTACLE − 1) = 252——是 Nav2 自己這兩處不一致。 誤差量 ln(253/252)/f,f=3 時 1.3 mm,實務可忽略。但它比「改個常數」更值得寫:這個「從 costmap 值反推距離」的技巧把一個模組的實作常數硬寫進另一個模組,任何一邊改了公式形狀,另一邊都不會有編譯錯誤、不會有警告,只會安靜地算出偏掉的距離。採信任一個 agent 的單邊結論,都會寫出不完整的東西。
R22.3 Pages 上的數學渲染核對與修正 實際載入線上頁面驗證 MathJax,而不是只看本地 markdown。數量與錯誤數都是乾淨的(feedback-control-pid-lqr 58/58、nav2-plugin-algorithms 23/23 全部渲染,0 個 <mjx-merror>,正文 0 個殘留的 \[ / $$),但截圖看才發現公式的下沿被裁掉——分數的分母、θ_los 這類下標只剩上半。成因是 _layouts/default.htmlmjx-container[display="true"]{overflow-y:hidden} 配上 body 繼承的 line-height:1.95(CJK 排版用的):行高把 CHTML 的內部盒子撐開,墨水超出容器,再被 overflow-y:hidden 切掉。修法是讓 MathJax 容器 line-height:normal 不繼承內文行高,並補 padding:.45em 0 的上下餘裕。這一修影響全站四篇有公式的文件 ✅ 完成
R23 站台版面改版與全站連結核對 garden-skillsweb-design-engineer 流程選一套具名 recipe 再落地,選的是 tufte-dataink(資訊架構派):零裝飾、圖表直接標註、短註走頁邊。兩處按實際條件改:紙面用中性偏白而非 recipe 的暖奶油(使用者指定不要土黃),中文正文維持黑體、襯線只用在標題/引言/頁邊註(CJK 襯線 webfont 動輒數 MB,不值得為排版味道拉進來)。關鍵路徑色從墨綠換成磚紅 #a6300e,全站仍只有一個。導覽補四件:頂部章節列、左欄同章節清單 + 頁內目次(捲動高亮)、麵包屑、上下篇;資料來源是 _data/nav.yml,由 scripts/gen-nav.py 從 README 的「文件索引」產生——索引本來就已經是閱讀順序,再手抄一份只會兩邊不同步。頁邊註的判準寫死在 layout 的 JS:main 的直接子 blockquote、純文字、150 字以內才浮到右邊界,長的留在正文。連結核對抓到一個從上線就存在的 bug:_config.ymlinclude: 比對的是目錄名不是相對路徑,寫 docs/_legacy 一行都沒生效,docs/_legacy_meta_refs 三個目錄從來沒有被發佈過,全站 13 條連結(README 佔 4 條)在線上是 404。改成 - _legacy / - _meta / - _refs 後,82 頁、3105 條站內連結、232 張圖全數命中,孤兒頁 0 ✅ 完成

R22.3 的教訓:統計乾淨不等於畫面正確

這一輪的檢查順序值得記下來,因為前三步全部通過、問題出在第四步:

  1. 本地 $$ 成對 ✓
  2. 線上 mjx-container 數量與原始檔公式數相符(58/58、23/23)✓
  3. <mjx-merror> 為 0、正文無殘留標記 ✓
  4. 截圖看 → 下標與分母被裁掉

前三項都是可程式化的統計,而它們對「內容被 CSS 切掉」這件事完全無感——MathJax 成功渲染了元素,DOM 裡什麼都在,只是被 overflow 藏起來。能用數據驗的就用數據驗這條原則的邊界正在這裡:數據能證明「東西在」,不能證明「看得到」。

與 R19 那個 img{height:auto} 蓋掉 HTML height 屬性的坑同源:版面 CSS 的副作用不會報錯,只會安靜地改變畫面,而且兩次都是全站範圍。

可重用的量測方法:別靠截圖判斷「有沒有被裁」

截圖能發現問題,但判斷「修好了沒」用截圖既貴又不精確(要裁對位置、要用 vision token)。正確的做法是把問題本身量成數字:對每個公式容器比較 scrollHeightclientHeight,差值 > 0 就是有內容被 overflow 藏起來。

做法是把線上 HTML 抓下來、在 </body> 前注入一段量測 script(等 MathJax 跑完再測),用 --dump-dom 取回結果:

c.scrollHeight - c.clientHeight > 1   →   這條公式有內容被裁,超出 N px

這個量測抓到了截圖看不出來的殘留:第一次把 padding 修成 .45em 之後,58 條裡已經全乾淨,但另一篇還有 1 條超出 3 px——AMCL 的運動模型是三行 aligned 環境,比單行公式高,餘裕不夠。提到 .7em 才收乾淨。3 px 用肉眼看截圖是看不出來的。

最終複驗四篇有公式的文件:feedback-control-pid-lqr 58 條、nav2-plugin-algorithms 23 條、robot-dynamics 22 條、gaussian-from-first-principles 5 條,合計 108 條公式,0 被裁、0 渲染錯誤

往後改 _layouts/ 的 CSS,順序是:先跑這個量測,再截一張圖做最終確認。

R23 的教訓:掃 markdown 會同時給你假警報和漏報

這一輪先用 python 掃 markdown 原始檔找壞連結,掃出 30 筆。逐項核對之後:

掃出來的 實際
17 筆「連到 README.md 會變成 README.html 而 404」 全是假的jekyll-relative-links 是拿站上的頁面 URL 去解析的,README.md 會正確變成該目錄的 index
9 筆「anchor 不存在」 全是假的。我自己寫的 slug 演算法跟 kramdown 不一致
真正壞掉的 13 條 一條都沒掃到——它們的目標檔案在 repo 裡確實存在,壞的是「這些檔案根本沒被發佈」

假警報與漏報都來自同一件事:掃的是輸入,不是產出。連結對不對取決於 Jekyll 實際產生了哪些檔案、kramdown 實際寫了哪些 id,這兩件事都只在 _site/ 裡才有答案。

所以流程固定成:Docker 裡 jekyll build(約 3 秒)→ 掃 _sitehref/srcid → 比對。順帶還能算出孤兒頁(沒有任何頁面連進去的檔案),那是掃原始檔算不出來的。

外部連結另外掃:抓 URL 時要分開處理 markdown 行內連結、<...> 自動連結與裸 URL,並剝掉尾隨的全形標點——不然 <https://renode.io/> 會被抓成 https://renode.io/> 而回報 404,一份乾淨的站看起來會像有上百條死連結。

外部連結:掃完之後還壞著的

510 條去重後的外部連結全掃過一遍。扣掉擷取假象(程式碼裡的 RMF_WEB_HOST 佔位、 被吃掉結尾括號的維基連結)與擋機器人的回應(GitHub 429 限流、iso.org / sciencedirect / elifesciences 的 403/406、st.com 要瀏覽器標頭才給 200),修掉的是這些:

原連結 現況 處置
docs.nav2.org 的 14 個目標 整站改版:加版本前綴 + 路徑重組 逐一找到新頁、實測 200 後替換(22 處)
irapkaist/scancontext repo owner 改名 gisbi-kim/scancontext;順帶結案 §8 那條「repo 路徑待查證」
Isaac Sim RTX Lidar 文件 檔名去掉 based isaacsim_sensors_rtx_lidar.html
Doyle 1978 的 Caltech PDF 該站已移除 改用同一行本來就寫著的 DOI
Stretch 3 硬體手冊 產品世代更新,整棵 0.3/ 樹消失 退到 hello-robot.com;沒有等價的 Stretch 3 頁可指

沒有修、確認是死的(找不到等價來源,替換等於換掉論據,不是修連結):

外部連結的維護成本跟站內連結不同:站內壞掉是自己的錯、修法唯一; 站外壞掉多半是對方改版或下架,能不能修取決於有沒有等價來源,沒有就該老實留著標記, 而不是隨手換一個看起來相關的頁面頂上——那會讓論據和來源對不上。

後續形態輪次(待做)

輪次 主題 內容
待排 移動操作 II 抓取與力控(夾爪 vs 吸盤、力/力矩感測、阻抗 vs 導納)、視覺伺服(eye-in-hand 標定、影像式 vs 位置式)
待排 人形 雙足平衡、全身控制(QP / 階層式 QP)、上肢操作、VLA 模型
待排 協作安全專篇 ISO 10218:2025 + 四種協作模式 + PFL 的力/壓力限值結構;需購買標準原文才能寫定論

判斷結論

內容原則