Skip to content

Commit bdeb606

Browse files
Introduce setUpClass, python snake_case variables
Test case fails if object depth z is not equal 1.
1 parent 19e8cde commit bdeb606

File tree

1 file changed

+53
-50
lines changed

1 file changed

+53
-50
lines changed

python/gtsam/tests/test_Cal3Fisheye.py

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,100 +5,103 @@
55
66
See LICENSE for the license information
77
8-
Cal3Unified unit tests.
8+
Cal3Fisheye unit tests.
99
Author: Frank Dellaert & Duy Nguyen Ta (Python)
10+
Refactored: Roderick Koehle
1011
"""
1112
import unittest
1213

1314
import numpy as np
1415

1516
import gtsam
1617
from gtsam.utils.test_case import GtsamTestCase
17-
18+
from gtsam.symbol_shorthand import K, L, P
1819

1920
class TestCal3Fisheye(GtsamTestCase):
20-
21+
22+
@classmethod
23+
def setUpClass(cls):
24+
"""
25+
Equidistant fisheye projection
26+
27+
An equidistant fisheye projection with focal length f is defined
28+
as the relation r/f = tan(theta), with r being the radius in the
29+
image plane and theta the incident angle of the object point.
30+
"""
31+
x, y, z = 1.0, 0.0, 1.0
32+
# x, y, z = 0.5, 0.0, 2.0 <== Note: this example fails!
33+
u, v = np.arctan2(x, z), 0.0
34+
cls.obj_point = np.array([x, y, z])
35+
cls.img_point = np.array([u, v])
36+
2137
def test_Cal3Fisheye(self):
2238
K = gtsam.Cal3Fisheye()
2339
self.assertEqual(K.fx(), 1.)
2440
self.assertEqual(K.fy(), 1.)
2541

2642
def test_distortion(self):
27-
"Equidistant fisheye model of focal length f, defined as r/f = tan(theta)"
43+
"""Fisheye distortion and rectification"""
2844
equidistant = gtsam.Cal3Fisheye()
29-
x, y, z = 1, 0, 1
30-
u, v = equidistant.uncalibrate([x, y])
31-
x2, y2 = equidistant.calibrate([u, v])
32-
self.assertAlmostEqual(u, np.arctan2(x, z))
33-
self.assertAlmostEqual(v, 0)
34-
self.assertAlmostEqual(x2, x)
35-
self.assertAlmostEqual(y2, 0)
45+
perspective_pt = self.obj_point[0:2]/self.obj_point[2]
46+
distorted_pt = equidistant.uncalibrate(perspective_pt)
47+
rectified_pt = equidistant.calibrate(distorted_pt)
48+
self.gtsamAssertEquals(distorted_pt, self.img_point)
49+
self.gtsamAssertEquals(rectified_pt, perspective_pt)
3650

3751
def test_pinhole(self):
38-
"Spatial equidistant camera projection"
39-
x, y, z = 1.0, 0.0, 1.0
40-
u, v = np.arctan2(x, z), 0.0
52+
"""Spatial equidistant camera projection"""
4153
camera = gtsam.PinholeCameraCal3Fisheye()
42-
43-
pt1 = camera.Project([x, y, z])
54+
pt1 = camera.Project(self.obj_point) # Perspective projection
55+
pt2 = camera.project(self.obj_point) # Equidistant projection
56+
x, y, z = self.obj_point
57+
obj1 = camera.backproject(self.img_point, z)
58+
r1 = camera.range(self.obj_point)
59+
r = np.linalg.norm(self.obj_point)
4460
self.gtsamAssertEquals(pt1, np.array([x/z, y/z]))
45-
46-
pt2 = camera.project([x, y, z])
47-
self.gtsamAssertEquals(pt2, np.array([u, v]))
48-
49-
obj1 = camera.backproject([u, v], z)
50-
self.gtsamAssertEquals(obj1, np.array([x, y, z]))
51-
52-
r1 = camera.range(np.array([x, y, z]))
53-
self.assertEqual(r1, np.linalg.norm([x, y, z]))
61+
self.gtsamAssertEquals(pt2, self.img_point)
62+
self.gtsamAssertEquals(obj1, self.obj_point)
63+
self.assertEqual(r1, r)
5464

5565
def test_generic_factor(self):
56-
"Evaluate residual using pose and point as state variables"
57-
objPoint = np.array([1, 0, 1])
58-
imgPoint = np.array([np.arctan2(objPoint[0], objPoint[2]), 0])
66+
"""Evaluate residual using pose and point as state variables"""
5967
graph = gtsam.NonlinearFactorGraph()
6068
state = gtsam.Values()
61-
measured = imgPoint
62-
noiseModel = gtsam.noiseModel.Isotropic.Sigma(2, 1)
63-
poseKey = gtsam.symbol_shorthand.P(0)
64-
pointKey = gtsam.symbol_shorthand.L(0)
69+
measured = self.img_point
70+
noise_model = gtsam.noiseModel.Isotropic.Sigma(2, 1)
71+
pose_key, point_key = P(0), L(0)
6572
k = gtsam.Cal3Fisheye()
66-
state.insert_pose3(poseKey, gtsam.Pose3())
67-
state.insert_point3(pointKey, gtsam.Point3(objPoint))
68-
factor = gtsam.GenericProjectionFactorCal3Fisheye(measured, noiseModel, poseKey, pointKey, k)
73+
state.insert_pose3(pose_key, gtsam.Pose3())
74+
state.insert_point3(point_key, self.obj_point)
75+
factor = gtsam.GenericProjectionFactorCal3Fisheye(measured, noise_model, pose_key, point_key, k)
6976
graph.add(factor)
7077
score = graph.error(state)
7178
self.assertAlmostEqual(score, 0)
7279

7380
def test_sfm_factor2(self):
74-
"Evaluate residual with camera, pose and point as state variables"
75-
objPoint = np.array([1, 0, 1])
76-
imgPoint = np.array([np.arctan2(objPoint[0], objPoint[2]), 0])
81+
"""Evaluate residual with camera, pose and point as state variables"""
7782
graph = gtsam.NonlinearFactorGraph()
7883
state = gtsam.Values()
79-
measured = imgPoint
80-
noiseModel = gtsam.noiseModel.Isotropic.Sigma(2, 1)
81-
cameraKey = gtsam.symbol_shorthand.K(0)
82-
poseKey = gtsam.symbol_shorthand.P(0)
83-
landmarkKey = gtsam.symbol_shorthand.L(0)
84+
measured = self.img_point
85+
noise_model = gtsam.noiseModel.Isotropic.Sigma(2, 1)
86+
camera_key, pose_key, landmark_key = K(0), P(0), L(0)
8487
k = gtsam.Cal3Fisheye()
85-
state.insert_cal3fisheye(cameraKey, k)
86-
state.insert_pose3(poseKey, gtsam.Pose3())
87-
state.insert_point3(landmarkKey, gtsam.Point3(objPoint))
88-
factor = gtsam.GeneralSFMFactor2Cal3Fisheye(measured, noiseModel, poseKey, landmarkKey, cameraKey)
88+
state.insert_cal3fisheye(camera_key, k)
89+
state.insert_pose3(pose_key, gtsam.Pose3())
90+
state.insert_point3(landmark_key, gtsam.Point3(self.obj_point))
91+
factor = gtsam.GeneralSFMFactor2Cal3Fisheye(measured, noise_model, pose_key, landmark_key, camera_key)
8992
graph.add(factor)
9093
score = graph.error(state)
9194
self.assertAlmostEqual(score, 0)
9295

9396
def test_retract(self):
9497
expected = gtsam.Cal3Fisheye(100 + 2, 105 + 3, 0.0 + 4, 320 + 5, 240 + 6,
9598
1e-3 + 7, 2.0*1e-3 + 8, 3.0*1e-3 + 9, 4.0*1e-3 + 10)
96-
K = gtsam.Cal3Fisheye(100, 105, 0.0, 320, 240,
99+
k = gtsam.Cal3Fisheye(100, 105, 0.0, 320, 240,
97100
1e-3, 2.0*1e-3, 3.0*1e-3, 4.0*1e-3)
98101
d = np.array([2, 3, 4, 5, 6, 7, 8, 9, 10], order='F')
99-
actual = K.retract(d)
102+
actual = k.retract(d)
100103
self.gtsamAssertEquals(actual, expected)
101-
np.testing.assert_allclose(d, K.localCoordinates(actual))
104+
np.testing.assert_allclose(d, k.localCoordinates(actual))
102105

103106

104107
if __name__ == "__main__":

0 commit comments

Comments
 (0)