Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of Off-Axis Parabolic Mirrors #23

Open
aglavic opened this issue Mar 15, 2018 · 7 comments
Open

Implementation of Off-Axis Parabolic Mirrors #23

aglavic opened this issue Mar 15, 2018 · 7 comments

Comments

@aglavic
Copy link

aglavic commented Mar 15, 2018

Hi,
thanks for providing this great library.

I'm trying to test and optimize an optical system that uses off-axis parabolic mirrors under 90° to relay an image. I did manage to get an imaging system with 90° reflection to work and also to produce the correct parabolic shape with conic constant=-1, but the optical axis is always at the pole of the parabola.

Is there any way to implement this component in rayopt correctly? And if not, how hard would it be to adapt the API to allow for this shape to be used?

Kind regards,

Artur

@jordens
Copy link
Member

jordens commented Mar 15, 2018

That should work using offset. Do you have a code snippet to show what you are trying to do?

@aglavic
Copy link
Author

aglavic commented Mar 15, 2018

Yes, with the offset I can bring the shape to the right position, but the active area is still at the pole. Here is an example:

s = system_from_yaml("""
description: three lens monochromatic focusing f/1 50mm
stop: 2
wavelengths: [550.0e-9]
object: {angle_deg: 9.0, pupil: {radius: 25}}
elements:
- {material: air, radius: 25}
- {material: mirror, radius: 25, roc: -50.0, offset: [0, -25, 150], angles: [-1.571, 0, 0], conic: -1}
- {material: glass/SCHOTT-SF|N-SF5, roc: 247.7, distance: 150, radius: 25, direction: [0, 1, 0]}
- {material: glass/SCHOTT-BK|N-BK7HT, roc: 72.1, distance: 3, radius: 25, direction: [0, 1, 0]}
- {material: air, roc: -83.2, distance: 12, radius: 25, direction: [0, 1, 0]}
- {material: air, distance: 2, radius: 22.0, direction: [0, 1, 0]}
- {material: glass/HIKARI-BaF|E-BAF11, roc: 50.8, distance: 3.8, radius: 25, direction: [0, 1, 0]}
- {material: glass/SCHOTT-SF|N-SF11, roc: -41.7, distance: 20, radius: 25, direction: [0, 1, 0]}
- {material: air, roc: -247.7, distance: 3, radius: 25, direction: [0, 1, 0]}
- {material: air, distance: 100, radius: 1, direction: [0, 1, 0]}
""")
s.object=FiniteConjugate(radius=25.0, pupil=dict(radius=25.0))
s.update()

@jordens
Copy link
Member

jordens commented Mar 15, 2018

I see. You'd want both an off-axis vertex and an off-vertex shape/aperture. That's not implemented yet. You can either subclass rayopt.elements.Spheroid and overload clip() and use that new class where you have that mirror. That should be smooth sailing if you know how you want that to look.
Or you can work around it and make the parabolic mirror symmetric (larger than and covering the actual piece) and just place a simple air-air interface that clips the rays to the desired aperture in front of the parabolic mirror at the shape and position where the actual cut parabola is.
Maybe adapt the offner relay example. Notice how during aiming the rays are clipped to hit the small convex mirror.

@aglavic
Copy link
Author

aglavic commented Mar 15, 2018

Thanks for the quick reply.

Overwriting the clip method does not seem to have the expected effect, at least on the way the rays are drawn. I tried to use a simple translation, which did not seem to change anything:

def clip(self, y, u):
        return super(OffClipSpheroid, self).clip(y-array([10., 0., 0.])[newaxis,:], u)

I also tried to use some air interfaces with the actual geometry, but now it does not seem to trace correctly:

s = system_from_yaml("""
description: three lens monochromatic focusing f/1 50mm
stop: 7
wavelengths: [550.0e-9]
object: {angle_deg: 9.0, pupil: {radius: 25}}
elements:
- {material: air, radius: 25}
- {material: mirror, radius: 35, offset: [0, 0, 50], angles: [-0.7853981633974483, 0, 0]}
- {material: air, offset: [0, 100, 100], radius: 25, angles: [0.78539816339744828,0,0]}
- {material: mirror, radius: 35, offset: [0, 150, -100], angles: [0.7853981633974483, 0, 0]}
- {material: air, offset: [0, -50, 0], radius: 25, angles: [-1.5707963267948966,0,0]}
- {material: glass/SCHOTT-SF|N-SF5, roc: 247.7, distance: 2, radius: 25, direction: [0,0,-1]}
- {material: glass/SCHOTT-BK|N-BK7HT, roc: 72.1, distance: 3, radius: 25, direction: [0, 0, -1]}
- {material: air, roc: -83.2, distance: 12, radius: 25, direction: [0, 0, -1]}
- {material: air, distance: 2, radius: 22.0, direction: [0, 0, -1]}
- {material: glass/HIKARI-BaF|E-BAF11, roc: 50.8, distance: 3.8, radius: 25, direction: [0, 0, -1]}
- {material: glass/SCHOTT-SF|N-SF11, roc: -41.7, distance: 20, radius: 25, direction: [0, 0, -1]}
- {material: air, roc: -247.7, distance: 3, radius: 25, direction: [0, 0, -1]}
- {material: air, distance: 100, radius: 1, direction: [0, 0, -1]}
""")
s.object=FiniteConjugate(radius=25.0, pupil=dict(radius=25.0))
s[1]=Spheroid(material='mirror', radius=130, roc=-100.0, offset=[0,-50,0], angles=[0, 0, 0], conic=-1)
s[3]=Spheroid(material='mirror', radius=130, roc=-100.0, offset=[0,150,-100], angles=[-arctan2(100,150), 0, 0], conic=-1)
s.update()

Is there a way I can simply trace one straight ray to see where it is going wrong?

@jordens
Copy link
Member

jordens commented Mar 15, 2018

Sure. Something like this (tweaking your first snippet):

s = ro.system_from_yaml("""
description: three lens monochromatic focusing f/1 50mm
stop: 2
wavelengths: [550.0e-9]
object: {angle_deg: 9.0, pupil: {radius: 25}}
elements:
- {material: air, radius: 25}
- {material: mirror, radius: 100, roc: -50.0, offset: [0, -25, 150], angles: [-1.1, 0, 0], conic: -1}
- {material: glass/SCHOTT-SF|N-SF5, roc: 247.7, distance: 150, radius: 25, direction: [0, 1, 0]}
- {material: glass/SCHOTT-BK|N-BK7HT, roc: 72.1, distance: 3, radius: 25, direction: [0, 1, 0]}
- {material: air, roc: -83.2, distance: 12, radius: 25, direction: [0, 1, 0]}
- {material: air, distance: 2, radius: 22.0, direction: [0, 1, 0]}
- {material: glass/HIKARI-BaF|E-BAF11, roc: 50.8, distance: 3.8, radius: 25, direction: [0, 1, 0]}
- {material: glass/SCHOTT-SF|N-SF11, roc: -41.7, distance: 20, radius: 25, direction: [0, 1, 0]}
- {material: air, roc: -247.7, distance: 3, radius: 25, direction: [0, 1, 0]}
- {material: air, distance: 100, radius: 1, direction: [0, 1, 0]}
""")
s.object = ro.FiniteConjugate(radius=25.0, pupil=dict(radius=25.0))
s.update()

g = ro.GeometricTrace(s)
g.rays_given(y=[(0., 0)], u=[(0., 0)])
g.propagate()
fig, ax = plt.subplots(figsize=(15, 15))
s.plot(ax)
g.plot(ax)

print(g)
ray 0
 # T         n   track z  rel path  height x  height y  height z   angle x   angle y   angle z
 0 S         1         0         0         0         0         0         0         0         1
 1 S         1     152.1     29.73         0      37.8    -14.29         0  -0.02949   -0.9996
 2 S     1.677     302.1     12.43         0     11.89    0.2854         0    0.1759    0.9844
 3 S     1.519     305.1     15.94         0     12.57     1.104         0    0.2138    0.9769
 4 S         1     317.1     18.85         0     14.67    -1.303         0    0.2332    0.9724
 5 S         1     319.1     20.25         0     15.46         0         0    0.2332    0.9724
 6 S      1.67     322.9      23.4         0     17.08     2.958         0 -0.009322         1
 7 S     1.791     342.9     25.84         0     16.96    -3.603         0   0.02142    0.9998
 8 S         1     345.9     33.61         0     17.09   -0.5899         0   -0.0163    0.9999
 9 S         1     445.9     34.24         0     15.45         0         0   -0.0163    0.9999

image

@aglavic
Copy link
Author

aglavic commented Mar 15, 2018

Thanks, that helped a lot.
So now it starts of correctly, but at the second mirror something strange happens that looks like the intersection does not find the right root:
image

Here is the code:

s = system_from_yaml("""
description: three lens monochromatic focusing f/1 50mm
stop: 3
wavelengths: [550.0e-9]
object: {angle_deg: 0.01, pupil: {radius: 25}}
elements:
- {material: air, radius: 25}
- {material: mirror, radius: 35, offset: [0, 0, 50], angles: [-0.7853981633974483, 0, 0]}
- {material: air, offset: [0, 100, 100], radius: 25, angles: [0,0,0]}
- {material: air, offset: [0, 100, 0], radius: 25}
- {material: mirror, radius: 35, offset: [0, 150, -100], angles: [0.7853981633974483, 0, 0]}
- {material: air, offset: [0, -50, 40], radius: 25, angles: [-1.5707963267948966,0,0]}
- {material: air, offset: [0, 0, -20], radius: 25, angles: [0,0,0]}
- {material: air, distance: 0}
""")
s.object=FiniteConjugate(radius=25.0, pupil=dict(radius=25.0))
s[1]=Spheroid(material='mirror', radius=130, roc=-100.0, offset=[0,-50,0], angles=[0, 0, 0], conic=-1)
s[2].angles=[arctan2(100,100), 0, 0]
s[4]=Spheroid(material='mirror', radius=130, roc=-100.0, offset=[0,80,-100], angles=[-arctan2(100,80), 0, 0], conic=-1)
s[5].angles=[arctan2(50,40), 0, 0]
s.update()

g = GeometricTrace(s)
g.rays_given(y=[(0., 0.), (0.,0.), (0.,-0.)], u=[(0., 0.), (0.,0.1), (0.,-0.1)])
g.propagate()
fig, ax = plt.subplots(figsize=(15, 15))
s.plot(ax)
g.plot(ax)

Any Idea what could cause this?

@jordens
Copy link
Member

jordens commented Mar 16, 2018

Hmm. Not immediately. That does look like a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants