**2 次元クアッドコプターをゼロからシミュレーションする**

- **目的:** 既存のライブラリを一切使わず、基本的な原理だけで完結した 2‑D クアッドコプタ―(四旋翼)シミュレーションを構築します。  
- **主な構成要素:**
  - 物理エンジン(ニュートン力学・オイラー積分)
  - モーター推力モデル
  - 制御系(PIDまたは単純フィードバックループ)
  - 可視化(基本的な 2‑D 描画)

- **概要手順:**
  1. 状態変数を定義する(位置・速度、姿勢・角速度)。  
  2. 運動方程式を実装する。  
  3. モーターのダイナミクスと推力計算を追加する。  
  4. ホバリングや目標軌道維持のために制御器を設計する。  
  5. シンプルな 2‑D ウィンドウでクアッドコプタ―を描画する。

- **参考リソース:**
  - 可視化用オープンソースライブラリ(例:Pygame、Matplotlib)。  
  - UAV ダイナミクスと制御理論に関する文献・資料。  

*ドキュメント終了*

2026/04/09 5:25

**2 次元クアッドコプターをゼロからシミュレーションする** - **目的:** 既存のライブラリを一切使わず、基本的な原理だけで完結した 2‑D クアッドコプタ―(四旋翼)シミュレーションを構築します。 - **主な構成要素:** - 物理エンジン(ニュートン力学・オイラー積分) - モーター推力モデル - 制御系(PIDまたは単純フィードバックループ) - 可視化(基本的な 2‑D 描画) - **概要手順:** 1. 状態変数を定義する(位置・速度、姿勢・角速度)。 2. 運動方程式を実装する。 3. モーターのダイナミクスと推力計算を追加する。 4. ホバリングや目標軌道維持のために制御器を設計する。 5. シンプルな 2‑D ウィンドウでクアッドコプタ―を描画する。 - **参考リソース:** - 可視化用オープンソースライブラリ(例:Pygame、Matplotlib)。 - UAV ダイナミクスと制御理論に関する文献・資料。 *ドキュメント終了*

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

要約:
この記事では、長さ (\ell) と質量 (m) を持つ2本のアームを備えた四足クルーター(クワッドコプター)の単純な二次元(平面)シミュレーションが示されています。座標は水平を (y)、垂直を (z)、(yz)-平面におけるヨー角 (\phi) と定義し、反時計回りを正とします。
力: 合計推力 (u_1 = F_1+F_2) はボディに垂直に作用し、トルク入力 (u_2 = (F_1-F_2)\ell) が回転を制御します。
運動方程式は
[ m,\ddot y = -\frac{u_1}{m}\sin\phi,\qquad m,\ddot z = \frac{u_1}{m}\cos\phi-g,\qquad I,\ddot\phi = \frac{u_2}{I}\ell . ]
状態ベクトルは (x=[y,z,\phi,\dot y,\dot z,\dot\phi]^T) であり、ダイナミクス関数 (f(x,u)) はそれに応じて定義されます。
例で使用した物理パラメータは、(m=0.8,\text{kg})、(g=9.81,\text{m/s}^2)、(\ell=0.5,\text{m})、および (I=1\times10^{-3},\text{kg·m}^2) です。
Euler 積分は (t\in[0,15]) s の範囲で 1000 ステップ((dt\approx0.015) s)を用いて行われます。二つのテストケースが示されています:(i) トルクゼロ ((u_1=mg+0.01,\text{N})、(u_2=0)) ではゆっくり上昇し、(y) と (\phi) は一定に保たれます; (ii) 非ゼロトルク ((u_1=mg+0.5,\text{N})、(u_2=5\times10^{-5},\text{N})) では機体が約3 rad 回転し、 (\cos\phi<g m/u_1) のときに揚力を失って落下します。
シミュレーションは (z<0)(地面衝突)になると終了します。
ダイナミクス、積分ループ、および位置・速度・入力の matplotlib プロットを実装した Python コードが提供されています。

本文

この投稿では、四つのプロペラを持つクアッドコプター(ドローン)の 2 D(平面)シミュレーションを構築します。
運動方程式を導出し、それらを状態空間形式に書き換えて Python で数値解析する方法を示します。


なぜクアッドコプターをシミュレートするのか?

制御器を設計したり、強化学習エージェントを訓練したりする場合、まずソフトウェア上で動作できるモデルが必要です。
この投稿では、2 D で最初にシミュレーションステップをゼロから構築し、制御へ進む前にダイナミクスを理解します。


問題設定と座標系

下図の自由体図(free‑body diagram)から始めます。
水平軸を (y)、垂直軸を (z) とし、右手則で (x) 軸はページ外に向かうようにします。

クアッドコプター本体は質量 (m) を持つ剛体で、中心点 (C) から長さ (\ell) の二本のアームを伸ばしています。
(yz)-平面内で角度 (\phi) に回転し、(\phi>0) は (y) 軸から (z) 軸への逆時計回りの回転です。
重力は下向きに作用し、その大きさは (mg) です。
各アームには推力を生むプロペラがあり、推力は本体に対して垂直であるとします。これらを (F_1) と (F_2) と表記します。


運動方程式の導出

自由体図からニュートン–オイラー剛体運動方程式を得ます:
(y) 軸と (z) 軸に沿った二つの直線運動方程式と、角度 (\phi) に関する回転方程式です。
(F_y) と (F_z) はそれぞれの軸方向の合力成分、(\tau) は合せん断モーメント、(I) は重心を通る慣性モーメントです。時間微分は点で示します。

[ \begin{aligned} m,\ddot y &= \sum F_y\ m,\ddot z &= \sum F_z\ I,\ddot\phi &= \sum\tau \end{aligned} ]

推力を (y) と (z) の方向に分解すると

[ \begin{aligned} m,\ddot y &= -(F_1+F_2)\sin\phi\ m,\ddot z &= (F_1+F_2)\cos\phi - mg\ I,\ddot\phi &= (F_1-F_2),\ell \end{aligned} ]


状態空間形式への変換

数値解析を行うために、まず状態空間形式に書き直します。
状態 (\mathbf x) をシステムを記述する最小集合の変数と定義し、入力 (\mathbf u) を制御対象の変数とします。

制御可能な量はプロペラ推力 (F_1) と (F_2) です。
直接用いる代わりに次のように入力ベクトルを定義すると、表現がシンプルになります。

[ \mathbf u = \begin{bmatrix} u_1\u_2 \end{bmatrix}

\begin{bmatrix} F_1+F_2\[2pt] F_1-F_2 \end{bmatrix}, ]

これを代入し、微分項を整理すると

[ \begin{aligned} \ddot y &= -,\frac{u_1}{m}\sin\phi\ \ddot z &= ;\frac{u_1}{m}\cos\phi - g\ \ddot\phi &= ;\frac{u_2}{I},\ell \end{aligned} ]

状態空間モデルは一階微分方程式であるため、状態ベクトルを次のように定義します。

[ \mathbf x = \begin{bmatrix} y\ z\ \phi\ \dot y\ \dot z\ \dot\phi \end{bmatrix}. ]

すると完全な一階システムは

[ \boxed{ \dot{\mathbf x} = \begin{bmatrix} \dot y\[2pt] \dot z\[2pt] \dot\phi\[4pt] -\dfrac{u_1}{m}\sin\phi\[6pt] \dfrac{u_1}{m}\cos\phi - g\[6pt] \dfrac{u_2}{I},\ell \end{bmatrix} }. ]


Python でのシミュレーション

import numpy as np
from numpy.typing import NDArray

# 物理パラメータ
m = 0.8          # [kg]
g = 9.81         # [m/s²]
l = 0.5          # [m]
I = 1e-3         # [kg·m²]

def dynamics(x: NDArray, u: NDArray) -> NDArray:
    y, z, phi, y_dot, z_dot, phi_dot = x
    return np.array([
        y_dot,
        z_dot,
        phi_dot,
        -u[0]/m * np.sin(phi),
        u[0]/m * np.cos(phi) - g,
        u[1]/I * l
    ])

dynamics
が定義できたら、オイラー法で一次微分方程式を解きます。

t_start, t_stop, n_steps = 0.0, 15.0, 1_000
t   = np.linspace(t_start, t_stop, n_steps)
dt  = t[1] - t[0]

x      = np.zeros((n_steps, 6))          # 状態軌跡
u      = np.zeros((n_steps, 2))          # 入力軌跡

# 重さよりわずかに大きい定数推力 → ゆっくり上昇
u[:, 0] = m * g + 0.01        # u1
u[:, 1] = 0.0                # u2 (トルクなし)

for i in range(n_steps-1):
    x[i+1] = x[i] + dynamics(x[i], u[i]) * dt

これが、運動方程式を導出し、状態空間形式に変換して Python で数値積分する一連のシミュレーションパイプラインです。


シミュレーションの実行

トルクゼロの場合

(u_2=0) のとき、クアッドコプターは回転しません。
垂直加速度は一定であるため、(z(t)) は二次関数的に増加し、(\dot z(t)) は線形に増加します。
(y) と (\phi) は定数のままです。


トルクありの場合

今度は非ゼロトルク入力 (u_2) を与え、合計推力 (u_1) も増やします。
この単純モデルには地面接触を考慮していないため、クアッドコプターが (z=0) 以下に到達したらシミュレーションを停止します。

# 新しい入力
u[:, 0] = m * g + 0.5     # より大きな推力
u[:, 1] = 5e-5            # 小さなトルク

eps = 1e-8
for i in range(n_steps-1):
    if x[i, 1] < -eps:   # クアッドコプターが墜落した
        t = t[:i]
        x = x[:i]
        u = u[:i]
        break
    x[i+1] = x[i] + dynamics(x[i], u[i]) * dt

角度はゆっくりと 0 から約 3 rad(ほぼ逆転)へ増加します。
最初は高さが上がりますが、(\phi) が大きくなるにつれて推力の垂直成分が減少し、((u_1/m)\cos\phi < g) になると重力が支配的になり、機体は落下します。


付録:プロットコード

import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator

fig, axes = plt.subplots(3, 1, sharex=True, figsize=(9, 7))

# 位置状態
ax0, ax0r = axes[0], axes[0].twinx()
ax0.plot(t, x[:, 0], label='y', color='C0')
ax0.plot(t, x[:, 1], label='z', color='C1')
ax0r.plot(t, x[:, 2], label=r'$\phi$', color='C2')
ax0.set_ylabel('Position [m]')
ax0r.set_ylabel('Angle [rad]')
ax0.set_title('位置状態')
lines0 = ax0.get_lines() + ax0r.get_lines()
ax0.legend(handles=lines0, labels=[l.get_label() for l in lines0])

# 速度状態
ax1, ax1r = axes[1], axes[1].twinx()
ax1.plot(t, x[:, 3], label=r'$\dot y$', color='C0')
ax1.plot(t, x[:, 4], label=r'$\dot z$', color='C1')
ax1r.plot(t, x[:, 5], label=r'$\dot\phi$', color='C2')
ax1.set_ylabel('Linear velocity [m/s]')
ax1r.set_ylabel('Angular velocity [rad/s]')
ax1.set_title('速度状態')
lines1 = ax1.get_lines() + ax1r.get_lines()
ax1.legend(handles=lines1, labels=[l.get_label() for l in lines1])

# 入力
axes[2].plot(t, u[:, 0], label='u₁')
axes[2].plot(t, u[:, 1], label='u₂')
axes[2].set_title('入力')
axes[2].set_ylabel('Input [N]')
axes[2].legend()

for ax in axes:
    ax.xaxis.set_major_locator(MultipleLocator(1))
    ax.set_xlabel('time [s]')
    ax.grid(True)

fig.suptitle('2‑D クアッドコプターシミュレーション')
fig.tight_layout()
plt.show()

注: 本投稿は完全に人間が執筆し、GPT‑5.4(Codex を経由)で校正/軽微編集を行いました。

同じ日のほかのニュース

一覧に戻る →

2026/04/11 7:16

MacBook の角を削り取ること (「Filing the corners off my MacBooks」という表現は、MacBookの角をサンドペーパーやファイルで磨き取り、角を丸めている様子を指します。)

## Japanese Translation: ### 改良された要約 著者は、2026年4月にMacBookの鋭い角を削る方法について説明し、手首に快適に感じられる滑らかでより人間工学的なエッジを目指したと述べています。Apple のアルミニウムユニボディ設計はこのような改造を可能にしますが、狭いノッチは不快感を与えることがあります。そのため、小さな半径の曲線を大きなものに統合しながら、機械を通過してしまわないよう段階的に作業することに重点を置いています。保護措置として、スピーカーとキーボードをテープで覆い、アルミニウム粉塵から守り、ファイル作業中は軽い圧力でラップトップを工作台にクランプしました。プロセスは粗いファイルで始め、その後 150 グリットのサンドペーパーで研磨し、最後に 400 グリットのサンドペーパーで仕上げました。著者は完成した表面品質に満足していると述べています。写真には数か月の使用で蓄積された傷やへこみが写っており、調整が必要だった理由を示しています。この改造は作業用コンピュータ上で行われたものであり、将来の作業用コンピュータも同様の変更を受ける可能性があることを示唆しています。著者は自分のノートパソコンを改造したい他者に対して助けを提供すると述べています

2026/04/11 9:10

アーテミス II は無事に海に帰還しました。

## Japanese Translation: > トランプ大統領はアーテミスIIクルーを称賛し、「現代の開拓者」と呼び、将来の火星ミッションへの示唆を投げかけました。オリオンカプセルは2026年4月10日、サンディエゴから40–50マイル離れた太平洋で午後8時7分(ET)に正確に着水し、乗組員4名が搭乗していました。回収は海軍潜水士と16〜20人のチームによって行われ、カプセルを安定させるためにシーアンカー、膨張式カラー、および筏を取り付けてから乗組員を救出しました。 > > 着水後、カプセルのシステムは電源を切りましたが、短時間の技術的な不具合により完全な電源復帰が回収チーム準備完了まで遅れました。再突入中、宇宙船は等離子体形成による6分間の通信遮断を経験し、熱シールドで約5,000°F(約2,760°C)の温度に達し、秒速約24,661mph(≈3.9Gs)まで加速しました。 > > 乗組員はiPhoneを使用して地球の最終写真を撮影し、「アースセット」と宇宙からしか観測できない月食も収録しました。また、指揮官レイド・ワイズマン氏の故人の妻に敬意を表し「キャロル」という月面クレーター名を付け、別の名前として「インテグリティ」の提案も検討しました。 > > 着水後、カプセルはUSS John P. Murthaへ運ばれ医療点検が行われ、その後海軍基地サンディエゴへ移送されてからケネディ宇宙センターに戻り検査とデータ解析が実施されました。ミッションは地球から最も遠い距離で252,756マイルという新記録を樹立し、アポロ13より4,000マイル以上離れた位置で月面上空4,067マイルを超える接近を達成しました。ミッション・コントロールは着水を「完璧な的中」と表現し、全システムが乗組員救出前に完全に機能していたことを確認しました。 > > CBSニュースは午後7時30分(ET)から着水の午後8時7分までライブ放送を行い、視聴者はオンラインまたはモバイルデバイスで視聴できました。乗組員の総ミッション期間は約9日1時間31分で、地球と月周回で推定694,481マイルに相当する距離を移動しました。 > > 成功裏に帰還したことでNASAのオリオン回収手順への信頼が強化され、将来の深宇宙計画(潜在的な火星ミッションを含む)を支援し、ライブメディア報道による公共の関与も向上しました。

2026/04/11 4:10

ウガンダで研究者らが指摘:チンパンジーは8年間にわたり「内戦」に陥っている ---

## Japanese Translation: (以下は日本語訳です) **改訂要旨** ウガンダのキバレ国立公園にあるンゴゴチンパンジーコミュニティ―かつて最大規模の野生集団(約200頭)―が、2015年6月の脱走をきっかけに、西部と中央という二つの対立派閥へと分裂しました。脱走後は6週間の回避期間が続き、その後対立が激化していきました。2018年までには両集団が完全に別々になり、西部チンパンジーは中央メンバーを標的にした攻撃を開始しました。 分裂以降、研究者たちは**24件の殺害事件**(少なくとも7頭の成人雄と17頭の乳幼児が中央集団から死亡)を記録しており、実際の死亡数はさらに多い可能性があります。暴力の主な要因として3つが挙げられます: 1. 2014年に5頭の成人雄と1頭の雌が死亡し、社会的ネットワークが崩壊したこと; 2. 2015年にアルファ雄が交代し、初期分裂と相まって影響を与えたこと; 3. 2017年に発生した呼吸器感染症流行で25頭のチンパンジー(中でも重要な集団間結びつき役)が死亡したこと。 著者アーロン・サンドルは、チンパンジーの領土性と外部との敵対的相互作用が、人間社会における宗教や政治といった文化的構造なしでも致命的な集団攻撃を引き起こす可能性があると強調しています。この研究は*Science*誌に掲載され、同誌のポッドキャストで取り上げられました。相関関係だけが戦争を説明できるという示唆は、人間の紛争根源を再考する必要性を訴えています。また、資源競争と雄対雄の繁殖闘争もエスカレーションに寄与した可能性が高く、集団分裂が社会を危険にさらす警告として提示されています。 この要旨は主要な事実を全て保持しつつ曖昧な表現を排除し、研究の広範な示唆を明確に記述しています。

**2 次元クアッドコプターをゼロからシミュレーションする** - **目的:** 既存のライブラリを一切使わず、基本的な原理だけで完結した 2‑D クアッドコプタ―(四旋翼)シミュレーションを構築します。 - **主な構成要素:** - 物理エンジン(ニュートン力学・オイラー積分) - モーター推力モデル - 制御系(PIDまたは単純フィードバックループ) - 可視化(基本的な 2‑D 描画) - **概要手順:** 1. 状態変数を定義する(位置・速度、姿勢・角速度)。 2. 運動方程式を実装する。 3. モーターのダイナミクスと推力計算を追加する。 4. ホバリングや目標軌道維持のために制御器を設計する。 5. シンプルな 2‑D ウィンドウでクアッドコプタ―を描画する。 - **参考リソース:** - 可視化用オープンソースライブラリ(例:Pygame、Matplotlib)。 - UAV ダイナミクスと制御理論に関する文献・資料。 *ドキュメント終了* | そっか~ニュース