构建镜头模型
让我们用这个包建立一个理想镜头的模型 GeometricalOptics.jl. 我们将展示如何在一个画布上显示光束传播的几个图形,并在这个图形上实现射线优化过程,使图形的信息量最大。
光学系统参数
要指定镜头参数,您需要连接(并可能安装)库 GeometricalOptics.
Pkg.add( url="https://github.com/airspaced-nk5/GeometricalOptics.jl#master" )
Pkg.add( "Optim" )
using GeometricalOptics
gr(); # Библиотека лучше работает с этим механизмом отрисовки графиков
现在我们可以指定几个球面透镜和一个像平面。:
/物体/类型|材料|折射率|半径R1(mm)|半径R2(mm)|厚度/跟踪距离。 |
| ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | ----------- |
/镜头/双凸/[SK16](https://refractiveindex.info/?shelf=glass&book ;=HIKARI-SK&page;=SK16) | 1.6204 | 22 | 430 | 3 | 6 |
/镜头/biconcave/[F2](https://refractiveindex.info/?shelf=glass&book ;=肖特-F&页;=F2) | 1.6200 | 22 | 20 | 1 | 6 |
/镜头/双凸/[SK16](https://refractiveindex.info/?shelf=glass&book ;=HIKARI-SK&page;=SK16) | 1.6204 | 78 | 16 | 3 | 34 |
光学系统的最后一个元件是像平面。
测量单位(毫米)在计算中不起特殊作用,只要我们不考虑衍射和波长。
透镜的厚度等于光线沿着光轴穿过透镜的路径长度。
半径R1和R2被理解为每个透镜的每一侧的曲率半径:R1表征位于更靠近光源的"输入"侧的曲率半径,R2是位于更靠近像平面的透镜的输出侧。
让我们来描述这个光学系统,并建立一个小的可视化。:
surfsList = [ spherical, spherical,
spherical, spherical,
spherical, spherical,
zplane]
p_s = 10; # Расстояние от левого края графика до первой преломляющей поверхности
stations = p_s .+ [ 0., 3., 9., 10., 16., 19., 53. ]
radii = [ 22., -430., -22., 20., 78., -16., 0.0 ]
coeffsList = [ [s, r] for (s,r) in zip(stations, radii)]
# Материал линз, по порядку: SK16, F2, SK16
nList = [ 1., 1.6204,
1., 1.6200,
1., 1.6204,
1.]
optSta = opticalstack( coeffsList, surfsList, nList );
test_bundle = bundle( [0.], (-3:3:3), 0., 0., 0. );
p_lens = optSta( test_bundle; rend = "YZ", halfdomain=3.5 )
plot!( ylimits=(-5,5), aspect_ratio=:none, size=(600,200) )
一个小小的可视化让我们看到所有指定的元素。
将光束瞄准孔径
现在让我们假设该系统具有位于凹透镜后2毫米的光圈。
我们希望将光束穿过它,设置一定的入射角,并确保它们聚焦在图像平面上。
我们可以将模型分成两部分,并模拟膜片在两个方向上的传播(一个表面模型) [6:end],另一个为 [5:-1:1]). 但是由于射线只有在接近第一个透镜时才应该平行(它们在穿过光阑时不会相互平行),我们必须在穿过光阑时寻找每条射线的角度。
让我们走另一条路,"优化"两个参数:光束宽度和光束中心光束指向的Y轴上的点。 我们的目标是找到射线正好穿过膜片的光束的参数。
angles = [0.0, 0.1, 0.2]; # углы каждого из пучков лучей
colors = [:blue, :green, :red]; # каждый пучок характеризуется своим цветом
ypositions_init = [ 0., 3.0, 5.0]; # приблизительное положение точки отправки центральных лучей по оси Y
bundle_halfwidth = 3; # радиус пучков света
p = plot(); # нанесем несколько графиков
for (angle, ypos, pc, plot_surface) in zip(angles, ypositions_init, colors, [true, false, false])
b = bundle([0.], range(-bundle_halfwidth,bundle_halfwidth,length=3) .- ypos, 0., angle, 0.)
optSta( b; rend = "YZ", color = pc, plobj = p, halfdomain=5.5, issurfplot=plot_surface )
end
plot!( p, p_s.+[12., 12.], [-2.5, 2.5], lw=2, lc=:black, markershape=:diamond, markercolor=:white );
plot!( p, ylimits=(-8,8), size=(900,400) )
如果我们放大光圈的图像,我们会看到我们的第一个近似值离所需的近似值不是很远,但是为了进行准确的计算,我们需要将光束发送的点移动一点。
光束与光轴的角度不会改变。 我们只是在寻找如何定位光束,使其精确地穿过隔膜。 这对于计算传感器尺寸和其他有趣的结果很有用。
plot!( xlimits=(p_s .+ [10, 14]), ylimits=(-3,3), aspect_ratio=:none, size=(500,500) )
现在让我们创建一个优化过程。
using Optim
# Новая конфигурация, которая "заканчивается" диафрагмой (хотя можно добавить zplane между любыми линзами)
optSta2 = opticalstack( [coeffsList[1:4]; [[p_s+12.]]], [surfsList[1:4]; zplane], [nList[1:4] ; 1.0] );
# Функция, которую мы будем оптимизировать
function f(x, in_angle)
b_hw = x[1] # радиус пучка
ypos = x[2] # смещение по Y центра пучка
b = bundle([0.], range(-b_hw,b_hw,length=3) .- ypos, 0., in_angle, 0.);
# Изучим пятно на пересечении пучка с 6-ой поверхностью
t_info = GeometricalOptics.trace_extract_terminus( optSta2( b ), 6, coord="y" );
# Два критерия оптимизации: обе границы светового пятна должны совпадать с размером диафрагмы
q1 = abs( minimum( t_info ) - (-2.5))
q2 = abs( maximum( t_info ) - ( 2.5))
return q1 + q2
end
angles_hw_list = []
y_positions_list = []
for (angle,y_pos_init) in zip(angles, ypositions_init)
# Выполняем оптимизацию для каждого нужного нам значения угла по-отдельности
res = optimize(x -> f(x, angle), [bundle_halfwidth, y_pos_init])
angle_optim, ypos_optim = Optim.minimizer( res )
push!( angles_hw_list, angle_optim )
push!( y_positions_list, ypos_optim )
end
# Выведем таблицу результатов оптимизации
display([["Направление луча"; "Ширина пучка"; "Отправная точка по Y"] [angles angles_hw_list y_positions_list]'] )
优化后,光学系统看起来像这样:
p = plot(); # Полотно для нанесения нескольких графиков
for (angle, ypos, b_hw, pc, plot_surface) in zip(angles, y_positions_list, angles_hw_list, colors, [true, false, false])
b = bundle([0.], range(-b_hw,b_hw,length=3) .- ypos, 0., angle, 0.)
optSta( b; rend = "YZ", color = pc, plobj = p, halfdomain=5.5, issurfplot=plot_surface )
end
plot!( p, p_s.+[12., 12.], [-2.5, 2.5], lw=2, lc=:black, markershape=:diamond, markercolor=:white );
plot!( p, ylimits=(-8,8), size=(900,400) )
仔细检查膜片可以让你看到光点的正确位置。
plot!( xlimits=(p_s .+ [10, 14]), ylimits=(-3,3), aspect_ratio=:none, size=(500,500) )
库中的镜头尺寸
GeometricalOptics.jl它们在视觉上没有被考虑在内。 在某些情况下,例如,当创建多项式Цернике,光束在某个区域之外的通过导致开发人员提供的误差。
结论
如果将光学电路计算功能包装在优化过程中,则可以自动化许多光学系统设计步骤。 光束由单独的光线组成,它们在系统任何部分的参数都可以使用函数获得 trace_extract_terminus 对她подобных.
在少量额外代码的帮助下,可以计算AF范围和其他任务。
数据来源
[[1]](http://mir-3d-world.ipo.spb.ru/2016/3dworld_4_2016.pdf )在Zemax中构建理想光学[电子资源]//科普杂志"3D世界世界":网站。 网址:http://mir-3d-world.ipo.spb.ru/2016/3dworld_4_2016.pdf (请求日期:05.11.2024)。



