はじめに
あるとき、お客様からこんな声をもらいました。
「Qタイプ非球面から偶数次非球面への変換精度があまり良くない」
Ansys Zemax OpticStudio (以下、Zemax)には非球面の変換機能がありますが、
改めて確認してみると、確かに変換後の性能に違和感があるケースがありました。
特に
- スマホレンズのような高次非球面
- 変曲点が多い形状
で、変換後のMTFが微妙に崩れることがあります。
Zemaxの非球面変換機能は何をやっているのか?
マニュアルを見てみると、Zemaxの非球面変換機能についてこんな一文がありました。
「変換は最小二乗フィッティングで実行されるので、変換の前後で面のサグの差の RMS 値が最小になります。」
つまり、
\min || z_{\text{original}} - z_{\text{converted}} ||
という問題を解いているわけです。
これは「形状(サグ量)を似せる」ことはできますが、
- 係数の意味は保持されない
- 可逆ではない
のではないかと考えられます。
特に変曲点が多い場合は、局所的な形状をうまく再現できず、
結果として光学性能(MTFなど)に差が出る可能性があります。
そもそもQタイプ非球面とは?
ここで改めて、Qタイプ非球面について整理します。
Qcon
Qconは、基本コーニック面を基準としたサグの逸脱量で表現され、Jacobi多項式を基底とします。
Shape specification for axially symmetric optical surfaces
概念的には、
z(r) = \text{基本Conic面} + \rho^2 \sum a_m Q_m(\rho^2)
のような形で表されるようです。
特徴:
- 基底がほぼ直交
- 係数の独立性が高い
- 最適化に強い
つまり、べき乗基底を使用する偶数次非球面(Even Asphere)とは根本的に違う座標系です。
Qbfs
QbfsはBest-Fit Sphere(最適球面)を基準とした傾斜の逸脱量のRMS値によって非球面を表現する面タイプです。
Manufacturability estimates for optical aspheres
- BFS(最適球面)をベースに展開
- 残差を効率的に表現
こちらもやはり基底が異なります。
あらためて偶数次非球面(Even Asphere)とは?
ここで一度、変換先として登場する
偶数次非球面(Even Asphere) についても整理しておきます。
Zemaxでいう偶数次非球面は、その名の通り
- 半径 $r$ の 偶数べき
- $r^4, r^6, r^8, \dots$
のみを用いてサグを表現する非球面です。
定義式
偶数次非球面では、レンズ面の子午線方向の高さ$z(r)$ を以下の式で表します。
z(r) = \frac{c r^2}{1 + \sqrt{\,1 - (1+k)c^2 r^2\,}}
+ \sum_{i=2}^{n} A_{2i} r^{2i}
\ , \ c = \frac{1}{R}
𝑅:曲率半径
𝑘:コーニック定数
A𝑖:非球面係数
上式が一般式です。
実際にZemaxで面タイプに「偶数次非球面(Even Asphere)」を選択した場合は
16次の項までが有効になるので以下式になります。
z(r) = \frac{c r^2}{1 + \sqrt{\,1 - (1+k)c^2 r^2\,}}
+ A_4 r^4 + A_6 r^6 + A_8 r^8 + A_{10} r^{10}
+ A_{12} r^{12} + A_{14} r^{14} + A_{16} r^{16}
ここで重要なのは、
- 基底は単純な多項式 $r^n$
- 各項は直交していない
という点です。
特徴
偶数次非球面は歴史的にも最も広く使われている非球面表現で、
数式が直感的で、加工機や評価測定機との対応が分かりやすいというメリットがあります。
一方で、
- 項同士の相関が強い
- 変曲点が複数ある面では局所的な形状再現が難しい
といった弱点もあります。
Qconとの本質的な違い
ここで、先ほど説明したQconと改めて比べてみます。
-
偶数次非球面(Even Asphere)
- 基底:$r^4, r^6, r^8, \dots$(べき乗基底)
- 直感的だが、項同士が干渉しやすい
-
Qcon
- 基底:Jacobi多項式に基づく特殊な多項式
- 係数の独立性が高く、最適化に強い
Jacobiとは?
続いて、「Jacobiって何?」を整理。
Jacobi多項式というのは、
ある区間の上で、都合よく性質をそろえた特別な多項式の列
と言えます。
例えば普通の多項式には
- 1(定数)
- $x$
- $x^2$
- $x^3$
等が含まれますが、これらは単純で分かりやすい代わりに、
最適化や展開のときに互いの役割がかなり被ります。
一方、Jacobi多項式は、
- 低次から高次へ順番に作れる
- 互いの役割が整理されている
- 直交性に近い良い性質を持つ
という特徴があります。
この「役割の被りにくさ」が重要です。
そのため、QconではJacobi系の基底を使うことで、
- 各係数が何をしているのか分かりやすくなる
- 最適化中に項同士がケンカしにくくなる
というメリットがあります。
Qconなら厳密変換できるのでは?
さて、前置きが長くなりましたがここからが今回の本題です。
偶数次非球面とQconは、
- どちらも「多項式表現」
- ただし基底が違うだけ
つまり、
⇒ 基底変換問題
として解けるはずでは?と考えられます。
数学的に考えてみる
偶数次非球面の追加項は、
A_4 r^4 + A_6 r^6 + A_8 r^8 + \cdots
なので、偶数次非球面は「$r$ の偶数べき」表現です。
一方、Qconは
\rho^2 \sum a_m Q_m(\rho^2)
このままだと偶数次非球面側は $r$、Qcon側は正規化された変数を使っていることになるので、
まずは両者を同じ土俵に乗せる必要があります。
ここで変数を
x = \left(\frac{r}{R_n}\right)^2
と置くと、
$r^4$は$x^2$、$r^6$は$x^3$、$r^8$は$x^4$
のように書けます。
つまり偶数次非球面も、結局は $x$の多項式になるということです。
一方Qcon側も、Jacobi多項式を使った $x$の多項式です。
両方とも $x$ の多項式なら、あとは
- $x^2$ の係数
- $x^3$ の係数
- $x^4$ の係数
を見比べればよいだけです。
実装のコア部分(Jacobi多項式)
というわけで、変換プログラムを書いてみました。
Qcon基底はJacobi多項式で定義されています。
実際のコード:
def jacobi_poly_coeffs(n, alpha, beta):
if n == 0:
return Polynomial([1.0])
if n == 1:
return Polynomial([0.5 * (alpha - beta), 0.5 * (alpha + beta + 2.0)])
Pnm1 = jacobi_poly_coeffs(1, alpha, beta)
Pnm2 = jacobi_poly_coeffs(0, alpha, beta)
for k in range(1, n):
kf = float(k)
a1 = 2 * (kf + 1) * (kf + alpha + beta + 1) * (2 * kf + alpha + beta)
a2 = (2 * kf + alpha + beta + 1) * ((2 * kf + alpha + beta + 2) * (2 * kf + alpha + beta))
a3 = (2 * kf + alpha + beta + 1) * (alpha * alpha - beta * beta)
a4 = 2 * (kf + alpha) * (kf + beta) * (2 * kf + alpha + beta + 2)
tpoly = Polynomial([0.0, 1.0])
num = (Pnm1 * (a2 * tpoly + Polynomial([a3])) - Pnm2 * a4)
Pnp1 = num * (1.0 / a1)
Pnm2, Pnm1 = Pnm1, Pnp1
return Pnm1
ポイント:
- SciPyを使わずに自前で実装しているので環境依存しない
- 多項式そのものを生成している
- 最適化による評価ではなく「係数変換」が目的
Qcon基底への変換
def qcon_Qm_con_coeffs(m):
Pm_t = jacobi_poly_coeffs(m, 0.0, 4.0)
t_of_x = Polynomial([-1.0, 2.0]) # 2x-1
Pm_x = Pm_t(t_of_x)
return Pm_x.coef
ここでは、
Q_m(x) = P_m^{(0,4)}(2x-1)
をそのままコードにしています。
係数変換
def even_to_qcon_exact(Rn, even_A):
N = len(even_A) + 1
M = N - 2
B = np.zeros(N + 1)
for j in range(2, N + 1):
B[j] = even_A[j - 2] * (Rn ** (2 * j))
q = [qcon_Qm_con_coeffs(m) for m in range(M + 1)]
a = np.zeros(M + 1)
a[M] = B[N] / q[M][M]
for n in range(M - 1, -1, -1):
j = n + 2
s = 0.0
for m in range(n + 1, M + 1):
s += a[m] * q[m][n]
a[n] = (B[j] - s) / q[n][n]
return a
- 偶数次非球面係数を、正規化変数$x$の式に直す
- Qcon基底を、同じく$x$の式として準備する
- 同じ形になるようにQcon係数を解く
ここで重要なのは(しつこいようですが)、
これはフィッティングではなく係数比較だということです。
Qbfsはどうする?
では、Qbfsの方も対応しようと試みますが、ここで問題が発生します。
Qbfsは、
- ベースがBest-Fit Sphere
- 基底が違う
つまり、
⇒ Qconのような厳密変換は難しい
そこで、結論:
- Qcon → 係数一致による厳密変換
- Qbfs → サグ量をサンプリングし最小二乗で係数を求める
という方針にしました。
ツールを作る
ということで、上記コードを基本に実際にツール化してみる。
方針は以下。
- ZOS-API(Python)を使用
- ZemaxでのGUI操作は一切不要で、独自GUIで完結させる
- レンズ読み込み → 変換 → 保存の一連の作業を実行する
実験してみた
サンプルレンズで比較しました。
「710_reoptimized_MTF_materials_QType.zmx」
こちらのページからダウンロードできるレンズデータを使用します。
プログラムを実行すると以下のような画面が出るようにしてみました。

対象となるレンズデータを読み込ませ、面番号を指定。
変換先の非球面タイプを指定します。
現状では変換パターンは6種になります。
- 偶数次非球面 ⇒ Qcon
R,k固定、係数数=7(A4~A16)、厳密変換 - 偶数次非球面 ⇒ Qbfs
R,k固定、係数数=7(A4~A16)、最小二乗(LSQ)フィット - Qcon ⇒ 偶数次非球面
R,k固定、係数数=変換前そのまま、7項までなら偶数次非球面、
それ以上なら拡張非球面に自動で変更し、厳密変換 - Qcon ⇒ Qbfs
R,k固定、係数数=変換前そのまま、LSQフィット - Qbfs ⇒ 偶数次非球面
R,k固定、係数数=変換前そのまま、7項までなら偶数次非球面、
それ以上なら拡張非球面に自動で変更し、LSQフィット - Qbfs ⇒ Qcon
R,k固定、係数数=変換前そのまま、LSQフィット
大事な前提として、
今回は基準のコーニック面は変えずに追加項の係数のみを変換する方針なので
曲率半径Rとコーニック定数kは常に固定です。
ここも変えたい場合はむしろZemaxの変換機能の方でサグ量を最適化した方が良いかと。
ここから、非球面度の高いレンズ最終面のみを変換して比較してみます。
Zemax標準変換
Zemaxの変換機能を使って最終面を偶数次非球面にサグ最適化した結果です。
MTFに若干の違いがありますね。
自作ツール
こちらが今回の自作ツールで変換した後です。
MTFがほぼ一致しました!
上手くいったのではないでしょうか^_^
結論
- Zemaxの変換機能は便利だが厳密ではない
- Qconは基底変換として解ける
- 一方でQbfsは近似が必要
おわりに
今回の検討で非球面変換は単なるフィッティングではないと理解できました。
また、ZOS-APIを使うと、こういった処理も柔軟に実装できることも再認識。
同じような課題を持っている方の参考になれば嬉しいです。
本記事は筆者個人の見解であり、
所属組織の公式見解を示すものではありません。
問い合わせ
本記事のプログラムに興味がある方はお問い合わせください。
また、本件に関わらず光学シミュレーションソフトの導入や技術相談、
設計解析委託をお考えの方もぜひサイバネットまで。
お気軽にこちらの問い合わせフォームよりご連絡ください👇
お問い合わせフォームはこちら



