
- Groupフェア班
- Date2025.09.06
遺伝的アルゴリズムを用いたフェアリングの対称翼設計
お久しぶりです。TBT26代フェアリング設計のきゃっぷです。活動日誌は2ヶ月に一回書かなければいけないという話だったのですが時は早いものでいつの間にか4か月も経ってしまっていました。時間の流れとは早いものです。
さて、今回は遺伝的アルゴリズムを使った翼型設計について話していこうと思います。
TBTでは遺伝的アルゴリズムが空前のブームとなっておりいろいろなものが遺伝的アルゴリズムにより作られようとしています。来年は遺伝的アルゴリズムシステムを推してコンテスト出場を目指すのもありでしょう。そんな遺伝的アルゴリズムですが、なんだそれ?って方もいると思うので説明させていただきます。
遺伝的アルゴリズムってなんだ?
「遺伝的アルゴリズム」ですが、名前だけ聞くと何やら難しそうですよね。でも、基本的な考え方はすごくシンプルで、一言でいうと「生物の進化をコンピュータ上で真似して、たくさんの候補の中から一番良い答えを見つけ出す方法」なんです。
進化論で「環境に適したものが生き残り、子孫を残していく」という話がありますよね。遺伝的アルゴリズムは、まさにこの仕組みを応用したものです。
これを僕たちの翼型設計に当てはめて、ざっくりと流れを説明するとこんな感じです。
Step 1:たくさんの翼型をランダムに作る(第一世代の誕生)
まず、コンピュータに「とりあえずこんな形はどう?」という感じで、多種多様な翼型(個体)をたくさん作らせます。この時点ではまだデタラメな形も多い、いわば翼型たちの第一世代です。
Step 2:それぞれの翼型を評価する(サバイバル開始) 次に、作った翼型一つひとつが、どれくらい「優秀か」をシミュレーションで評価して点数付けします。僕たちの場合なら、「揚力が高くて、抵抗が小さい翼型」ほど高い点数がつきます。これがその翼型の適応度になります。
Step 3:優秀な翼型を選び出す(選択と淘汰) 点数が高かった、つまり優秀な翼型たちを生き残らせます。逆に、点数が低かったダメな翼型はここでサヨナラです(淘汰)。まさに自然淘汰ですね。
Step 4:優秀な翼型同士で子供を作る(交叉) 生き残った優秀な翼型たちをペアにして、それぞれの特徴をうまく混ぜ合わせ、新しい「子供の翼型」をたくさん作ります。例えば、Aの翼型の前側の形と、Bの翼型の後ろ側の形を組み合わせる、といった感じです。親の良いとこ取りをした、さらに優秀な子供が生まれることが期待できます。これを**交叉(こうさ)**と呼びます。
Step 5:たまに突然変異を起こす(新しい可能性) 新しく生まれた子供の翼型の形を、ごく稀に、ほんの少しだけランダムに変化させることがあります。これが突然変異です。これにより、今までの世代にはなかった全く新しい特徴が生まれ、予想外のすごい性能を持つ翼型が誕生するかもしれません。
そして、Step 2〜5をひたすら繰り返す!
この「評価 → 選択 → 交叉 → 突然変異」というサイクルを、コンピュータ上で何百世代と高速で繰り返していきます。世代を重ねるごとに、翼型の集団はどんどん優秀なものに進化していきます。
そして最終的に、とてつもない世代交代の果てに生き残った最も優秀な翼型、それが僕たちが求める「最適解」というわけです。
面白いですよね!この方法を使えば、もしかしたら僕たちが思いもつかないような、理想的な翼型を生み出せるかもしれないんです。
以下からは具体なコードを説明していきます。興味があればどうぞ。(ちなみに僕も全くわかりません)
Python
def generate_naca_symmetric_coords(max_thickness, n_points=81):
"""NACA 4桁の対称翼型の座標を生成する関数"""
theta = np.linspace(0, np.pi, n_points)
x = 0.5 * (1 - np.cos(theta))
y_t = 5 * max_thickness * (0.2969 * np.sqrt(x) - 0.1260 * x - 0.3516 * x**2 + 0.2843 * x**3 - 0.1036 * x**4)
return x, y_t
翼の形を数式から作る
これはNACA4桁の公式を使って、指定された最大翼厚 (max_thickness
) を持つ対称翼型の座標データを生成する関数です。max_thickness=0.21
を与えれば、NACA0021の形状データが作られます。遺伝的アルゴリズムなどに応用する際は、この部分をCST法のような別の翼型生成方法に置き換えることになります。
干渉の制約(キープアウトゾーン) フェアリングの中にはパイロットが座ります。GAが生み出した理想の翼型が、パイロットの頭や、操作する舵の動きとぶつかって(干渉して)しまっては意味がありません。そこで、「この四角いエリアは窓だから、翼型がはみ出しちゃダメ」「この部分は操縦桿が動くからスペースを空けておく」といった**「立入禁止区域(キープアウトゾーン)」**を設定します。
Python
def run_xfoil_analysis(airfoil_name, x_coords, y_coords, alpha, re):
"""
指定された翼型と条件でXFOIL解析を1回実行し、CDとxtr_topの値を返す。(PACC版)
"""
XFOIL解析を実行する心臓部
この関数がコードの最も重要な部分です。翼型の座標データ (x_coords
, y_coords
) と解析条件(迎角alpha
、レイノルズ数re
)を受け取り、XFOILを自動操縦して性能を計算させ、結果を返します。
Python
commands = f"""
LOAD {shape_filename}
PANE
OPER
VISC {re}
PACC{polar_filename}
ITER 200
ALFA {alpha}
QUIT
"""
XFOILに送る「命令書」を作る
ここがXFOILを自動操縦している核心部です。人間が手で入力するコマンドを文字列として作成し、ファイルに書き出します。
LOAD ...
: 翼型データを読み込むVISC {re}
: 流れの粘性を考慮したモード(粘性モード)にし、レイノルズ数を設定するPACC...
: 解析結果をpolar_filename
という名前のファイルに自動で記録させるALFA {alpha}
: 指定した迎角で計算を実行する
Python
subprocess.run(bat_filename, shell=True, timeout=60, creationflags=CREATE_NO_WINDOW)
PythonからXFOILを起動
上で作成した命令書(コマンドファイル)を使って、実際にxfoil.exe
を実行しています。subprocess.run
は、Pythonプログラムの中から別のプログラム(今回はXFOIL)を呼び出すための命令です。
Python
if os.path.exists(polar_filename):
with open(polar_filename, 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in reversed(lines):
parts = line.strip().split()
if len(parts) >= 7:
try:
cd_value = float(parts[2])
xtr_top_value = float(parts[5])
# ...
break
XFOILの計算結果を読み取る
XFOILが polar_filename
に書き出した計算結果のファイルを開き、その中から必要な情報(3列目の抗力係数CD
と6列目の遷移点xtr_top
)を探し出して数値として取り出しています。
Python
if __name__ == "__main__":
# --- STEP 1: 翼型を定義 ---
airfoil_name = "NACA0021"
max_thickness = 0.21
# --- STEP 2: 解析条件を定義 ---
alpha = 0
reynolds_number = 1500000.0
# --- STEP 3: XFOIL解析を実行 ---
final_cd, final_xtr = run_xfoil_analysis(...)
実際にプログラムを実行する部分
最後に、このブロックで具体的な翼型(NACA0021)と解析条件(迎角0度、レイノルズ数150万)を設定し、上で解説した関数を呼び出して解析を実行、得られた結果を画面に表示しています。この部分のパラメータを変えることで、様々な翼型や条件でのテストが簡単に行えます。
最後に
今回の活動日誌は、少し専門的な内容になってしまいましたが、楽しんでいただけたでしょうか。
最終的な判断を下すのは人間の役割ですが、遺伝的アルゴリズムのようなパワフルなツールは、設計者の可能性を何倍にも引き上げてくれる強力なパートナーです。試行錯誤はまだまだ続きますが、応援よろしくお願いします!次回の活動日誌も、お楽しみに。