Monado OpenXR Runtime
Loading...
Searching...
No Matches
refine_lambda.h
Go to the documentation of this file.
1// Copyright 2019, Philipp Zabel
2// Copyright 2026, Beyley Cardellio
3// SPDX-License-Identifier: BSL-1.0
4/*!
5 * @file
6 * @brief Gauss-Newton refinement of Λ, specialized for P3P solving.
7 * @author Philipp Zabel <philipp.zabel@gmail.com>
8 * @author Beyley Cardellio <ep1cm1n10n123@gmail.com>
9 * @ingroup xrt_iface
10 */
11
12#pragma once
13
14#include <math.h>
15
16
17/*
18 * The number of iterations is chosen to just match the precision of the
19 * original Lambda Twist implementation.
20 * Increasing this further, we'd reach the point of diminishing returns.
21 */
22#define REFINE_LAMBDA_ITERATIONS 5
23
24/*
25 * Section 3.8 "Implementation Details" states:
26 *
27 * "Specifically, we refine the solution using a few verified steps of
28 * Gauss-Newton optimization on the sum of squares of Eqn (4)."
29 *
30 * Equation 4 in the paper:
31 *
32 * Λ^T M₁₂ Λ = a₁₂, Λ^T M₁₃ Λ = a₁₃, Λ^T M₂₃ Λ = a₂₃ (4)
33 *
34 * where
35 *
36 * ⎛ 1 -b₁₂ 0 ⎞ ⎛ 1 0 -b₁₃⎞ ⎛ 0 0 0 ⎞
37 * M₁₂ = ⎜-b₁₂ 1 0 ⎟, M₁₃ = ⎜ 0 0 0 ⎟, M₂₃ = ⎜ 0 1 -b₂₃⎟.
38 * ⎝ 0 0 0 ⎠ ⎝-b₁₃ 0 1 ⎠ ⎝ 0 -b₂₃ 1 ⎠
39 *
40 * thus refine Λ towards:
41 *
42 * λ₁² - 2b₁₂λ₁λ₂ + λ₂² - a₁₂ = 0
43 * λ₁² - 2b₁₃λ₁λ₃ + λ₃² - a₁₃ = 0
44 * λ₂² - 2b₂₃λ₂λ₃ + λ₃² - a₂₃ = 0
45 *
46 */
47static inline void
48gauss_newton_refineL(double *L, double a12, double a13, double a23, double b12, double b13, double b23)
49{
50 double l1 = L[0];
51 double l2 = L[1];
52 double l3 = L[2];
53
54 for (int i = 0; i < REFINE_LAMBDA_ITERATIONS; i++) {
55 /* λᵢ² */
56 const double l1_sq = l1 * l1;
57 const double l2_sq = l2 * l2;
58 const double l3_sq = l3 * l3;
59
60 /* residuals r(Λ) = λᵢ² - 2bᵢⱼλᵢλⱼ + λⱼ² - aᵢⱼ */
61 const double r1 = l1_sq - 2.0 * b12 * l1 * l2 + l2_sq - a12;
62 const double r2 = l1_sq - 2.0 * b13 * l1 * l3 + l3_sq - a13;
63 const double r3 = l2_sq - 2.0 * b23 * l2 * l3 + l3_sq - a23;
64
65 /* bail early if the solution is good enough */
66 if (fabs(r1) + fabs(r2) + fabs(r3) < 1e-10) {
67 break;
68 }
69
70 /*
71 * ⎛ λ₁-b₁₂λ₂ λ₂-b₁₂λ₁ 0 ⎞
72 * Jᵢⱼ = ∂rᵢ/∂λⱼ = 2 ⎜ λ₁-b₁₃λ₃ 0 λ₃-b₁₃λ₁⎟
73 * ⎝ 0 λ₂-b₂₃λ₃ λ₃-b₂₃λ₂⎠
74 */
75 const double j0 = l1 - b12 * l2; /* ½∂r₁/∂λ₁ */
76 const double j1 = l2 - b12 * l1; /* ½∂r₁/∂λ₂ */
77 const double j3 = l1 - b13 * l3; /* ½∂r₂/∂λ₁ */
78 const double j5 = l3 - b13 * l1; /* ½∂r₂/∂λ₃ */
79 const double j7 = l2 - b23 * l3; /* ½∂r₃/∂λ₂ */
80 const double j8 = l3 - b23 * l2; /* ½∂r₃/∂λ₃ */
81
82 /* 4 / det(J) */
83 const double det = 0.5 / (-j0 * j5 * j7 - j1 * j3 * j8);
84
85 /* Λ = Λ - J⁻¹ * r(Λ) */
86 l1 -= det * (-j5 * j7 * r1 - j1 * j8 * r2 + j1 * j5 * r3);
87 l2 -= det * (-j3 * j8 * r1 + j0 * j8 * r2 - j0 * j5 * r3);
88 l3 -= det * (j3 * j7 * r1 - j0 * j7 * r2 - j1 * j3 * r3);
89 }
90
91 L[0] = l1;
92 L[1] = l2;
93 L[2] = l3;
94}