← AIバイブコーディングTips 一覧へ Free Surface / Holding Torque

液面は式で解かず、二分探索で決める

液体の入った容器を反転させる治具を設計するとき、どの角度で何N·m必要になるのか。手を動かす前に知りたいのに、傾いた容器の中の液面位置は場合分けが多くて式が立てにくい。そこで解析的に解くのをやめ、AIに簡易モデルを書かせて数値解法で押し切った。結果、最悪条件が直感と違う場所にあることが分かった。

この記事で手に入るもの

傾斜角ごとの保持トルクを出す4ステップの計算手順と、それが正しいと確かめるための4つの検算。さらに実測で分かった設計上の要点——最悪充填率は50%、回転軸のオフセットが支配的(9倍)、満量では原理的にゼロ

01 — 問題設定

「反転させるのに何N·m要るか」を、現物なしで知りたい

液体の入った容器を、軸まわりに0°から180°まで回して中身を出す——このとき人や機構が支える必要のあるトルクは、角度によって変わる。設計で欲しいのはピーク値と、それが何度で起きるかだ。ここが分からないと、吊具・減速機・操作レバーのどれも寸法が決まらない。

厄介なのは液面が常に水平であるという点だ。容器が傾いても中の液体は水平面を保つので、容器から見た液体の形は角度ごとに変わる。三角形になったり、五角形になったり、上辺が容器の口を越えたりする。この場合分けを全部数式で書き下すのは面倒で、しかも間違えても気づきにくい。

今回は寸法が公開されている一斗缶(238 × 238 × 349 mm)を題材に、この計算を組んだ。


02 — 手法

4ステップで、角度からトルクへ

解析解を諦めて、幾何演算だけで組み立てる。各ステップは単純で、独立に検算できる。

01

容器を回す(液面ではなく容器を動かす)

容器の4隅を回転行列で回す。液面を傾けるのではなく容器を傾けるので、以降「水平線」は常に画面の水平のままでよくなる。場合分けが激減する最初の一手。

02

水平線で切って、面積が合う高さを二分探索する

ある高さ y の水平線より下だけを残すクリップ関数を作る。あとは「切った面積 = 目標体積」になる y二分探索で40回詰めるだけ。液面の形が何角形になろうと、コードは一つで済む。

02'

(排出時)口の高さより上は捨てる

注ぎ口が液面より下がった瞬間から中身は出ていく。口の高さで先にクリップして「入りうる最大量」を求め、目標体積がそれを超えていたら超過分を捨てて質量を減らす。

03

多角形の重心を出す

残った液体多角形に、多角形重心の公式をそのまま当てる。ここは定型処理。

04

支点まわりのモーメントに直す

支点を原点に置いておけば、モーメントアームは重心のx座標そのものT = m·g·xG で終わり。操作力は腕の長さで割って F = T / L

// 02 の中核。液面の形を場合分けせずに決める
function findLiquidPolygon(pts, targetArea) {
  let minY = Math.min(...pts.map(p => p.y));
  let maxY = Math.max(...pts.map(p => p.y));
  let poly = [];
  for (let i = 0; i < 40; i++) {          // 40回で十分
    const midY = (minY + maxY) / 2;
    poly = clipPolygonBelowY(pts, midY);      // 水平線で切る
    if (getPolygonArea(poly) < targetArea) maxY = midY;
    else minY = midY;
  }
  return poly;
}

03 — 検算

「それっぽい数字」を信じないための4つの確認

数値解法は、間違っていてももっともらしい値を返す。だから動かす前に、答えが既知になる条件を4つ用意して当てた。

二分探索は本当に収束しているか切り出した液体多角形の面積を、目標面積と突き合わせた。相対誤差は 1×10⁻¹² 〜 1×10⁻¹³ 台。40回で倍精度の限界近くまで詰まっている。
満量でゼロになるか充填率100%では液体が容器全体を占めるので、重心は容器の重心=支点に一致し、トルクは原理的にゼロのはず。全角度で0.00 N·m になった。
密度に比例するか質量は密度に比例し、トルクは質量に比例する。密度を2.0倍にしたら 20.65 → 41.30 N·m。ちょうど2倍。
充填率50%を軸に対称になるか支点が容器の中心にあるとき、充填率 f1−f のトルクは理論上ぴったり一致する(液体と空隙が点対称の補集合になるため)。実測は下表のとおり。
充填率最大トルク対になる充填率最大トルク一致
30%2.29 N·m70%2.29 N·m
40%2.97 N·m60%2.97 N·m
45%3.14 N·m55%3.14 N·m
20%1.76 N·m80%1.76 N·m

この一致が効いた。数値解法の実装ミスは、こういう厳密に成り立つはずの対称性を壊す形で出やすい。小数点以下2桁まで完全に一致したことで、クリップ・面積・重心の3つの関数がまとめて信用できるようになった。答えが分かっている条件を先に用意しておくのは、AIに書かせたコードを検品する常套手段でもある。


04 — 分かったこと

最悪条件は、直感とずれた場所にあった

① 一番きついのは「半分入っているとき」

充填率を10%から100%まで振って各条件の最大トルクを取ると、50%が最悪(3.20 N·m)で、そこから増やしても減らしても軽くなる。満タンが一番重い、は間違いだった。満量では自由表面が消えて液体が動けなくなるので、むしろ最も安定する。

充填率(%) 最大トルク 50% / 3.20 100% / 0.00 10 50 100
充填率と最大トルクの関係(密度1.0・オフセット0・実測値をプロット)。50%を頂点とする左右対称の山形になり、満量でゼロへ落ちる。

② 効くのは傾斜角ではなく、回転軸のズレ

回転軸が容器の重心を通っていれば、どの角度でもトルクは小さいままだった(最大2.29 N·m)。ところが回転軸を150mmずらすと、最大20.65 N·m まで跳ね上がる。約9倍

条件最大トルク発生角度倍率
オフセット 0mm2.29 N·m40°1.0×
オフセット 150mm20.65 N·m79°9.0×
オフセット 150mm・密度2.041.30 N·m79°18.0×

設計判断としてはこれが一番効く。治具の軸位置を容器の重心に寄せることが、レバーを長くするより先にやるべきことだと数字で言える。ピーク角度も40°から79°へ移動するので、「どこで踏ん張る設計にするか」も変わる。

③ 割り切った前提(ここを書かないと使えない)

実機の設計に使うなら、ここに安全率を掛けたうえで、最終的には実測で裏を取ることになる。この手法の役割は当たりをつけて設計の初期値を決めることであって、検証を置き換えるものではない。


05 — 持ち帰り

この手法が効く条件

今回の題材は液体入り容器だったが、同じ型が使えるのは次のような場面だ。

場合分けが多くて式が立てにくい形状が条件で変わるなら、解析解を諦めて「切る→測る→詰める」の数値解法に逃がす。コードは一つで済む。
答えが分かる条件を作れる満量・対称・比例のように、理論値が事前に言える条件が3つ以上作れるなら、実装の正しさを自分で確かめられる。
全域を掃きたい1点の答えより「どこが最悪か」が欲しい設計では、2度刻みで全走査してグラフにするほうが速い。人間が微分してピークを探す必要がない。

AIに実務ツールを書かせるとき、一番危ないのは「動いた」と「正しい」を混同することだ。今回は先に検算条件を4つ決めてから走らせた。逆に言えば、検算条件を思いつけない対象には、この手法を使わないほうがいい。実際この過程で、グラフの軸ラベルの符号がコード側の判定と食い違っている不具合も見つかっている。専門知識なしでAIに実務ツールを書かせる話の続きとして、「書かせたあと、どう信じるか」の部分にあたる。