Skip to content

Commit 6caa229

Browse files
committed
fix inverse kinematics dev notebook
1 parent 75b3fb1 commit 6caa229

File tree

7 files changed

+140
-20
lines changed

7 files changed

+140
-20
lines changed

dev_notebooks/inverse_kinematics.ipynb

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,36 @@
2727
"import torch.nn as nn\n",
2828
"import torchlensmaker as tlm\n",
2929
"\n",
30-
"y1 = tlm.parameter(torch.tensor(-20))\n",
31-
"z1 = tlm.parameter(torch.tensor(0))\n",
32-
"\n",
33-
"y2 = tlm.parameter(torch.tensor(0))\n",
34-
"z2 = tlm.parameter(torch.tensor(0))\n",
35-
"\n",
36-
"length1 = tlm.parameter(10.)\n",
3730
"\n",
31+
"# Custom element for the kinematic target\n",
3832
"class Target(tlm.SequentialElement):\n",
3933
" def __init__(self, point):\n",
4034
" super().__init__()\n",
4135
" self.point = point\n",
4236
"\n",
4337
" def forward(self, inputs):\n",
4438
" return inputs.replace(loss=torch.linalg.vector_norm(inputs.target() - self.point))\n",
39+
" \n",
40+
"\n",
41+
"# Trainable elements\n",
42+
"length1 = tlm.Gap(10)\n",
43+
"rotate1 = tlm.Rotate3D(-20, 0, trainable=True)\n",
44+
"rotate2 = tlm.Rotate3D(0, 0, trainable=True)\n",
4545
"\n",
4646
"model = tlm.Sequential(\n",
47-
" tlm.Gap(length1),\n",
48-
" tlm.Rotate3D(y1, z1),\n",
47+
" length1,\n",
48+
" rotate1,\n",
4949
" tlm.Gap(5),\n",
50-
" tlm.Rotate3D(y2, z2),\n",
50+
" rotate2,\n",
5151
" tlm.Gap(5),\n",
52-
" Target(torch.Tensor([20, 6, 6])),\n",
52+
" tlm.Gap(0),\n",
53+
" Target(torch.Tensor([10, 6, 6])),\n",
5354
")\n",
5455
"\n",
5556
"for name, param in model.named_parameters():\n",
5657
" print(name, param)\n",
5758
"\n",
58-
"tlm.show3d(model)"
59+
"tlm.show3d(model, controls={\"show_optical_axis\": True, \"show_other_axes\": True, \"show_kinematic_joints\": True})"
5960
]
6061
},
6162
{
@@ -75,13 +76,13 @@
7576
" num_iter = 100\n",
7677
").plot()\n",
7778
"\n",
78-
"print(\"length:\", length1.item())\n",
79-
"print(\"y1:\", torch.rad2deg(y1).detach().numpy())\n",
80-
"print(\"z1:\", torch.rad2deg(z1).detach().numpy())\n",
81-
"print(\"y2:\", torch.rad2deg(y2).detach().numpy())\n",
82-
"print(\"z2:\", torch.rad2deg(z2).detach().numpy())\n",
79+
"print(\"length:\", length1.x.item())\n",
80+
"print(\"y1:\", rotate1.y.item())\n",
81+
"print(\"z1:\", rotate1.z.item())\n",
82+
"print(\"y2:\", rotate2.y.item())\n",
83+
"print(\"z2:\", rotate2.z.item())\n",
8384
"\n",
84-
"tlm.show3d(model)"
85+
"tlm.show3d(model, controls={\"show_optical_axis\": True, \"show_other_axes\": True, \"show_kinematic_joints\": True})"
8586
]
8687
},
8788
{

docs/src/dev_notebooks.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ documentation. But you're welcome to look around 😊
1616
* [dev_notebooks/double_gauss.md](dev_notebooks/double_gauss.md)
1717
* [dev_notebooks/index_example.md](dev_notebooks/index_example.md)
1818
* [dev_notebooks/interval_arithmetic.md](dev_notebooks/interval_arithmetic.md)
19+
* [dev_notebooks/inverse_kinematics.md](dev_notebooks/inverse_kinematics.md)
1920
* [dev_notebooks/magnifying_glass.md](dev_notebooks/magnifying_glass.md)
2021
* [dev_notebooks/material_models.md](dev_notebooks/material_models.md)
2122
* [dev_notebooks/new_lenses.md](dev_notebooks/new_lenses.md)
@@ -30,3 +31,4 @@ documentation. But you're welcome to look around 😊
3031
* [dev_notebooks/test_reverse.md](dev_notebooks/test_reverse.md)
3132

3233

34+
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Inverse kinematics
2+
3+
An example of how tlm can be used to solve a simple 3D inverse kinematics problem.
4+
5+
6+
```python
7+
import torch
8+
import torch.nn as nn
9+
import torchlensmaker as tlm
10+
11+
12+
# Custom element for the kinematic target
13+
class Target(tlm.SequentialElement):
14+
def __init__(self, point):
15+
super().__init__()
16+
self.point = point
17+
18+
def forward(self, inputs):
19+
return inputs.replace(loss=torch.linalg.vector_norm(inputs.target() - self.point))
20+
21+
22+
# Trainable elements
23+
length1 = tlm.Gap(10)
24+
rotate1 = tlm.Rotate3D(-20, 0, trainable=True)
25+
rotate2 = tlm.Rotate3D(0, 0, trainable=True)
26+
27+
model = tlm.Sequential(
28+
length1,
29+
rotate1,
30+
tlm.Gap(5),
31+
rotate2,
32+
tlm.Gap(5),
33+
tlm.Gap(0),
34+
Target(torch.Tensor([10, 6, 6])),
35+
)
36+
37+
for name, param in model.named_parameters():
38+
print(name, param)
39+
40+
tlm.show3d(model, controls={"show_optical_axis": True, "show_other_axes": True, "show_kinematic_joints": True})
41+
```
42+
43+
1.y Parameter containing:
44+
tensor(-20., requires_grad=True)
45+
1.z Parameter containing:
46+
tensor(0., requires_grad=True)
47+
3.y Parameter containing:
48+
tensor(0., requires_grad=True)
49+
3.z Parameter containing:
50+
tensor(0., requires_grad=True)
51+
52+
53+
54+
<TLMViewer src="./inverse_kinematics_files/inverse_kinematics_0.json?url" />
55+
56+
57+
58+
```python
59+
import torch.optim as optim
60+
61+
62+
tlm.optimize(
63+
model,
64+
optimizer = optim.Adam(model.parameters(), lr=0.5),
65+
dim = 3,
66+
num_iter = 100
67+
).plot()
68+
69+
print("length:", length1.x.item())
70+
print("y1:", rotate1.y.item())
71+
print("z1:", rotate1.z.item())
72+
print("y2:", rotate2.y.item())
73+
print("z2:", rotate2.z.item())
74+
75+
tlm.show3d(model, controls={"show_optical_axis": True, "show_other_axes": True, "show_kinematic_joints": True})
76+
```
77+
78+
[ 1/100] L= 11.44367 | grad norm= 0.1403931826353073
79+
[ 6/100] L= 10.76307 | grad norm= 0.14587511122226715
80+
[ 11/100] L= 10.05291 | grad norm= 0.15076681971549988
81+
[ 16/100] L= 9.31445 | grad norm= 0.15501873195171356
82+
[ 21/100] L= 8.54986 | grad norm= 0.15856528282165527
83+
[ 26/100] L= 7.76245 | grad norm= 0.1613226681947708
84+
[ 31/100] L= 6.95688 | grad norm= 0.16318339109420776
85+
[ 36/100] L= 6.13927 | grad norm= 0.16400396823883057
86+
[ 41/100] L= 5.31753 | grad norm= 0.16357924044132233
87+
[ 46/100] L= 4.50185 | grad norm= 0.16159076988697052
88+
[ 51/100] L= 3.70584 | grad norm= 0.1575057953596115
89+
[ 56/100] L= 2.94863 | grad norm= 0.1504034548997879
90+
[ 61/100] L= 2.25887 | grad norm= 0.13884197175502777
91+
[ 66/100] L= 1.67854 | grad norm= 0.12194743007421494
92+
[ 71/100] L= 1.25048 | grad norm= 0.10576562583446503
93+
[ 76/100] L= 0.96030 | grad norm= 0.10391374677419662
94+
[ 81/100] L= 0.72035 | grad norm= 0.10480377823114395
95+
[ 86/100] L= 0.51991 | grad norm= 0.07430887967348099
96+
[ 91/100] L= 0.48093 | grad norm= 0.05209997668862343
97+
[ 96/100] L= 0.49441 | grad norm= 0.07413405179977417
98+
[100/100] L= 0.44278 | grad norm= 0.06729049235582352
99+
100+
101+
102+
103+
![png](inverse_kinematics_files/inverse_kinematics_3_1.png)
104+
105+
106+
107+
length: 10.0
108+
y1: -61.200279235839844
109+
z1: 30.05259895324707
110+
y2: -48.507781982421875
111+
z2: 31.085248947143555
112+
113+
114+
115+
<TLMViewer src="./inverse_kinematics_files/inverse_kinematics_1.json?url" />
116+
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"mode": "3D", "camera": "orthographic", "data": [{"type": "points", "data": [[0.0, 0.0, 0.0]], "layers": [4]}, {"type": "points", "data": [[10.0, 0.0, 0.0]], "layers": [4]}, {"type": "points", "data": [[10.0, 0.0, 0.0]], "layers": [4]}, {"type": "points", "data": [[14.69846344, 0.0, 1.71010065]], "layers": [4]}, {"type": "points", "data": [[14.69846344, 0.0, 1.71010065]], "layers": [4]}]}
1+
{"mode": "3D", "camera": "orthographic", "data": [{"type": "points", "data": [[0.0, 0.0, 0.0]], "layers": [4]}, {"type": "points", "data": [[10.0, 0.0, 0.0]], "layers": [4]}, {"type": "points", "data": [[10.0, 0.0, 0.0]], "layers": [4]}, {"type": "points", "data": [[14.69846344, 0.0, 1.71010065]], "layers": [4]}, {"type": "points", "data": [[14.69846344, 0.0, 1.71010065]], "layers": [4]}, {"type": "points", "data": [[19.39692688, 0.0, 3.4202013]], "layers": [4]}], "controls": {"show_optical_axis": true, "show_other_axes": true, "show_kinematic_joints": true}}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"mode": "3D", "camera": "orthographic", "data": [{"type": "points", "data": [[0.0, 0.0, 0.0]], "layers": [4]}, {"type": "points", "data": [[10.0, 0.0, 0.0]], "layers": [4]}, {"type": "points", "data": [[10.0, 0.0, 0.0]], "layers": [4]}, {"type": "points", "data": [[12.08492947, 2.5039742, 3.79251671]], "layers": [4]}, {"type": "points", "data": [[12.08492947, 2.5039742, 3.79251671]], "layers": [4]}, {"type": "points", "data": [[9.83437061, 6.15919542, 6.35656548]], "layers": [4]}], "controls": {"show_optical_axis": true, "show_other_axes": true, "show_kinematic_joints": true}}
33.2 KB
Loading

docs/src/doc/features.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ This effectively defines what robotics calls a [forward kinematic
150150
chain](https://en.wikipedia.org/wiki/Forward_kinematics). When optimizing not
151151
just surface shapes, but also the transforms themselves (like gap size or lens
152152
tilt), the library can be effectively used as an [inverse kinematic
153-
solver](/test_notebooks/inverse_kinematics).
153+
solver](/dev_notebooks/inverse_kinematics).
154154

155155
This is useful for example when optimizing the surface shape of a two lens
156156
system, and still wanting the second lens to be at a fixed distance from the

0 commit comments

Comments
 (0)