よしだの自習室

N重振り子シミュレーター

設定

1. これは何?

N重振り子のシミュレーターです。 ChatGPT にいろいろ教えてもらいながらなので、変なところがあるかも。

このドキュメントでは、HTML/CSS/JavaScript で実装した n 重振り子シミュレータ の主要ロジックを解説します。 シンプル化のため一部 UI 機能は隠蔽し、物理モデルと描画実装にフォーカスしています。

2. 振り子の運動方程式

2.1 Lagrangian からの導出

n 重振り子の Lagrangian $L$ は各振り子の運動エネルギーと位置エネルギーの差として表され、最終的に以下の連立方程式が得られます:

\[\sum_{j=1}^n M_{ij}\,\ddot\theta_j = b_i,\quad i=1,\dots,n\]

ここで

\[\eqalign{ S_i &= \sum_{k=i}^n m_k, \\ M_{ij} &= L_iL_jS_{\max(i,j)}\cos(\theta_i-\theta_j) }\] \[\eqalign{ b_i ={}& -gL_iS_i\sin\theta_i \\ &- \sum_{j=1}^{i-1}L_iL_jS_i\,\omega_j^2\sin(\theta_i-\theta_j) \\ &- \sum_{j=i+1}^n L_iL_jS_j\,\omega_j^2\sin(\theta_i-\theta_j) \\ &- \gamma\,\omega_i. }\]
  • $L_i$:振り子の長さ $[\mathrm{m}]$
  • $m_i$:質量 $[\mathrm{kg}]$
  • $g=9.80665\ [\mathrm{m/s^2}]$
  • $\gamma$:一般化座標に対する粘性減衰係数 $[\mathrm{kg\cdot m^2/s}]$

2.2 コード化

// computeAccelerationsFromState(): 状態から角加速度 α を求める
const L = this.lengths.map(px => px/this.pixelsPerMeter); // [m]
let M = Array(n).fill().map(_=>Array(n).fill(0)), b = Array(n).fill(0);
// M, b を構築...
let alpha = this.solveLinearSystem(M, b);

3. 数値積分

Runge‑Kutta 4(RK4)

updateRK4(dt) {
  const deriv = s => ({ dAngles: s.angularVelocities, dAngularVelocities: this.computeAccelerationsFromState(s) });
  // k1–k4 の評価を経て θ, ω を更新...
}

4. 描画について

  • 二重 Canvas
    • trailCanvas:各ジョイント軌跡を半透明でフェード
    • rodCanvas:毎フレームクリアしてロッド+ジョイントを再描画
// getPositions(): physics(m)→描画(px)の変換
const meter = this.lengths[i]/this.pixelsPerMeter;
x += meter*Math.sin(this.angles[i])*this.pixelsPerMeter;
[BACK TO TOP]