この記事では、シーケンシャル面をグリッド サグに置き換える Mathematica と Matlab のコードを取り上げます。生成されるグリッド サグ面は、ユーザーが指定した RMS 値と空間周波数を持つ同心円状のリップル パターンを特徴としています。ダイヤモンド旋削加工に起因して中域空間周波数で発生する誤差を表現する場合に、この機能が特に有用です。
著者 Alexandra Culler & Erin Elliott
ダウンロード
イントロダクション
一連の記事では、「 How to use the Grid Sag surface type 」にて、グリッド サグ面を手動でインポートする方法を、「 How to write a Grid Sag DAT file programmatically」にて、DAT ファイルをプログラムで生成する方法を取り上げました。つづいて、「ZOS-API を用いて任意のシーケンシャル面をグリッド サグ面に変換する方法」では、ZOS-API を使用して面の情報を取得し、面をそれと同等なグリッド サグに置き換える方法を紹介しました。ここでは、これらのツールを組み合わせ、光学系の面に同心円状のリップルを適用する方法を紹介します。このリップルは、製造段階で発生する可能性のある誤差を相殺することを目的としています。
非球面やフリーフォーム面の製造では、ダイヤモンド旋削法が広く使用されています。しかし、この加工法では、中域空間周波数を持つ誤差が増加することがあり、「面リップル」として知られる形状が発生します。
中域空間周波数 (MSF) での誤差は、周期が 2 mm から 0.2 mm の範囲にあります。MSF 誤差は、制御が容易ではないことから特に面倒な存在です。高域空間周波数での誤差の場合は、光の散乱が発生しますが、これは光学系の損失として扱うことができます。同様に、低域空間周波数での誤差は、通常はゼルニケ分解を使用して対策することができる形状誤差として扱えます。一方、MSF 誤差は、ゼルニケ項では制御できず、光学系での単純な損失として扱うこともできません。[1] 現在のところ、この誤差に対処する最良の方法は、この誤差を光学系の公差として扱うことです。その方法としてグリッド サグ面の使用があります。
一連の記事に関する注記とこのチュートリアルでの前提条件
この記事は、グリッド サグ面と API の利用に関する一連の記事のチュートリアルの第 4 部です。したがって、この記事では前回のチュートリアルを理解していることを前提としています。特に、添付のコードでは、各種のモジュール (Mathematica) と関数 (Matlab) を使用して冗長な手順を簡素化しています。これらは「How to convert any sequential surface to a Grid Sag Surface using the ZOS-API」で説明しているもので、次のモジュールと関数があります。
- LDE の表示 (
displayLDE
) - システム エクスプローラの表示 (
displaySystemData
) - サグのプロファイルの確認 (
getSag
) - サグの配列の生成 (
getExtendedSag
) - DAT ファイルの生成 (
makeDatFile
)
Matlab では、これらの関数が別のクラス ファイルになっていて、次の宣言でコードにロードされます。
MyFunctions = KBA4Tools;
このクラスを使用するには、関連する残りのコードと同じフォルダに KBA4Tools.m が存在する必要があります。このクラスの関数を呼び出すには、次の構文を使用します。
myNewVariable = MyFunctions.functionName( Inputs )
サンプル ファイル「Cooke 40 degree field.zmx」を開いて光学系の観察
作業を開始するに当たり、添付の API プログラムによって、デフォルトで設定されている {Zemax}\Samples フォルダに API フォルダがあるかどうかが確認されます。このフォルダが存在しない場合は、自動的に作成されます。
この確認が完了すると、{Zemax}\Samples\Sequential\Objectives にある Cooke 40 degree field.zmx ファイルが API によって開き、適切な API フォルダに別名で保存されます。この別名は「Cooke 40 degree field_Surf1_GridSag_AddRipple.zmx」です。
このファイルを API によって正しく取得したことを確認するために、レンズ データ エディタとシステム エクスプローラの各モジュールを使用して現在の光学系を確認します。
現在の光学系性能の確認
「ZOS-API を用いて任意のシーケンシャル面をグリッド サグ面に変換する方法」の記事では、OpticStudio 内で光学系の性能を手動で確認しました。そのため、以下の設定で標準スポット ダイアグラムと波面収差マップの出力を表示していました。
- [解析] (Analyze) → [光線とスポット] (Rays & Spots) → [標準スポット ダイアグラム] (Standard Spot Diagram) に移動してスポット ダイアグラムにアクセスします。光線密度を 25 に更新します。
- [解析] (Analyze) → [波面収差] (Wavefront) → [波面収差マップ] (Wavefront Map) に移動して波面収差マップにアクセスします。解像度を 512x512 に更新します。
今回は ZOS-API を使用して、今度はデータを取得します。これらのツールは ZOSAPI.Analysis 名前空間から利用します。データを取得する前に、ZOSAPI.Analysis.Settings.IAS_ インターフェイスを使用して、宣言した設定に一致するように各ウィンドウを更新できます。
取得したデータは以下のようになります。
また、波面収差マップは以下のように得られます。
これで、適用したリップル関数に起因して光学系に発生する変化をモニタリングできるようになりました。複数の面のデフォーメーションをテストする際に、このモニタリング方法は効果的です。
同心円状リップル変動の生成と追加
初期サグ情報の取得
サグ情報の取得と記述に使用する解像度の値が必要です。「ZOS-API を用いて任意のシーケンシャル面をグリッド サグ面に変換する方法」の説明にあるように、OpticStudio に用意されている解像度の値である 512 をこの解像度として使用します。この解像度を使用し、目的の面のサイズに基づいて点の間隔が生成されます。上記の宣言を以下に示します。
surfaceNumber = 1;
resolution = 512;
surfaceSemiDiameter = theLDE.GetSurfaceAt(surfaceNumber).SemiDiameter;
pointSpacing = (2 * surfaceSemiDiameter) / resolution;
用意されている関数 getSag
を使用して、面のサグのプロットを API に取得できます。つづいて、 getExtendedSag
関数を使用してサグ データの配列を生成できます。
面の定性解析には、マトリックス "startingSag" を使用します。DAT ファイルでマトリックス "initialSagData" を使用して、生成したリップルと結合します。
リップルの入力
中域空間周波数での誤差 (真の球面からの偏差) はリップルとして存在しています。この誤差を適切に表現するには次の値が必要です。
- リップルの高さ、つまり偏差の RMS 値または P-V 値
- リップルの周波数
このチュートリアルでは、以下の式を使用してリップルを生成します。
ここで、
- a : リップルの振幅。この値は、対象とする面の偏差の RMS 値に関連しています。
- b : 目的とするリップルの周波数。
- x と y : 対象とする面上での位置。
RMS 誤差の目標値である 0.1 波長と、空間周波数の目標値である 5.263 (リング数の 50 を半径で除算した値) から開始します。
rippleEquation を使用して、面上のさまざまな点での値を表すデータのマトリックスを生成します。値 x と y は面上の位置であり、マトリックスの中で各位置に続く位置は pointSpacing 値で区切って記述します。a は推定値 (1) で、b は余弦関数の周期です。この周期は、空間周波数の目標値に 2πを乗算して計算します。
targetRMS = 0.1;
targetSpatialFrequency = 50 / surfaceSemiDiameter;
convertRMS = targetRMS * (testWavelength * 10^-9) * 1000;
avalGuess = 1;
bval = 2 * (PI) * targetSpatialFreq;
振幅と面の偏差の RMS 値との間に直接の対応関係はないので、振幅は推測値から開始する必要があります。得られたリップルのマトリックスの RMS 値から反復計算で適切な振幅を求めることができます。ここで使用しているような簡潔な余弦であれば、必要な反復は 1 回のみであることがわかります。
「ZOS-API を用いて任意のシーケンシャル面をグリッド サグ面に変換する方法」の説明にあるように、linspace 関数を使用し、Matlab で x 値と y 値の配列を生成します。
xdir = linspace(-surfaceSemiDiameter, surfaceSemiDiameter, (resolution + 1));
ydir = linspace(-surfaceSemiDiameter, surfaceSemiDiameter, (resolution + 1));
for col1 = 1:length(rippleEquation)
for row1 = 1:length(rippleEquation)
rippleEquation(col1, row1) = avalGuess * cos(sqrt((xdir(col1)^2)+(ydir(row1)^2)) * bval);
end
end
次に以下のコードを使用して、リップルの現在の RMS 値を求めることができます。つづいて、その値を RMS の目標値と比較し、両者の比率から新しい aval 値を生成できます。
Matlab では次のようになります。
flatRipple = rippleEquation(:);
flatRipple = flatRipple(flatRipple~=0);
currentRMS = sqrt(var(flatRipple));
currentRMS が convertRMS に等しくない場合は、新しい aval の計算のみを実行します。これらの値が等しい場合は、次のように testRipple マトリックスを初期のサグ プロファイルと結合できます。
newSurfaceSag = initialSagData + testRipple;
第面 1 の置き換えと新しい光学系の確認
newSurfaceSag マトリックスを使用して、必要な DAT ファイルを生成し、作成済みの光学系の中で面を置き換えます。ここからは、「ZOS-API を用いて任意のシーケンシャル面をグリッド サグ面に変換する方法」の説明にある手順に従います。モジュールや関数を使用して DAT ファイルの作成を自動化します。
まず、作成するファイルの名前を surf1Ripple とします。
% Apply to the file
filename = "surf1Ripple.dat";
これで、この DAT ファイルを生成して光学系にインポートできます。makeDatFile
関数の出力が、この DAT ファイルの名前として使用されます。これにより、この出力がインポート関数に直接渡されます。
surfaceData = MyFunctions.makeDATFile(newSurfaceSag, filename, resolution + 1, pointSpacing);
surface = TheLDE.GetSurfaceAt(surfaceNumber);
surfaceTypeSettings = surface.GetSurfaceTypeSettings(ZOSAPI.Editors.LDE.SurfaceType.GridSag);
surface.ChangeType(surfaceTypeSettings);
surface.Radius = 0;
surface.Conic = 0;
surface.ImportData.ImportDataFile(surfaceData);
displayLDE
関数またはモジュールを使用することで、ファイルが適切に読み込まれたかを確認できます。
また、OpticStudio から新しいサグ情報を直接取得して、初期サグ情報を減算することで、リップルが加算されたことも確認できます。この様子を次の図に示します。
最後に、スポット ダイアグラムと波面収差マップのデータを取得することで、新しい光学系の仕様を確認できます。その結果を以下に示します。
想定したとおり、この結果は公称の光学系の仕様とは異なっています。この原因は、リップル パターンによって像の位置が変化したことにあります。ファイルを保存して開くと、更新されたレイアウトを表示できます。
面のリップルすべてを公差解析するには、性能データを取得する前に何らかの補償を適用することが適切な場合があります。
自動化に向けた関数の生成
「ZOS-API を用いて任意のシーケンシャル面をグリッド サグ面に変換する方法」の説明にあるように、繰り返し実行するタスクや複数の光学系で実行するタスク向けに、モジュールと関数を作成しておくと便利です。このチュートリアルを完了すると、新しい関数として次の 5 点を作成できます。
getSpotDiagramInfo
: 標準スポット ダイアグラムを開き、そこから情報を取得します。getWFE
: 波面収差マップを開き、そこからデータを取得します。calculateRMS
: 指定の配列の RMS を求めます。generateRipple
: 同心円状のリップル関数を配列に書き込みます。addRippleToSurface
: getExtendedSag 関数と generateRipple 関数を使用して、対象とする面のサグ データを取得し、面リップルの変動でそのデータを更新します。
新しい 5 つのモジュールは、添付されている Mathematica ファイル末尾のセクション 8 に置かれます。新しい 5 つの関数は、関数ファイル FullModuleTools.m に用意されます。
Mathematica の構文に関する注記
- Mathematica の各種モジュールは、独立した文書で用意されるのではなく、本書の冒頭に読み込まれます。
- Mathematica では、次のテーブル関数を使用して値のマトリックスを生成できます。
testRipple = Table[rippleEquation[avalGuess, bval, x, y], {x, -surfaceSemiDiameter, surfaceSemiDiameter}, {y, -surfaceSemiDiameter, surfaceSemiDiameter}];
- Mathematica では、RMS 出力をテストして振幅値を確認するプロセスを次のように実行できます。
flatRipple = Flatten[DeleteCases[testRipple, 0, Infinity]];
currentRMS = (Variance[flatRipple])^(1/2)
aval = convertRMS / currentRMS
リップルを適用するための別の方法について
この記事では取り上げていませんが、元の面サグを先に取得しなくてもリップル データを適用できます。グリッド サグ面を使用すると、球面、コーニック非球面、多項式非球面、ゼルニケ非球面の各項を定義できます。元の面でこれらの項 (半径、コーニック、追加データのパラメータ) を適用していれば、それらをグリッド サグ面のパラメータにコピーできます。これにより、DAT ファイルに置く必要があるデータは、面に追加する「追加サグ」としてのリップル データのみとなります。
参考文献
[1] Richard N. Youngworth, Benjamin B. Gallagher, and Brian L. Stamper "An overview of power spectral density (PSD) calculations", Proc. SPIE 5869, Optical Manufacturing and Testing VI, 58690U (18 August 2005); https://doi.org/10.1117/12.618478
KA-01970
コメント
記事コメントは受け付けていません。